在另一个编译单元中将lambda函数转换为普通函数会提高编译时间吗? 我正在研究一个C++服务器项目,它一直在增长着主()/函数,代码基础已经增长到一个点,即使在对主())/>函数进行了一点改动之后,编译时间大约为6分钟(在调试模式下)。(函数的main()大约有5000行长!)
我使用的是Visual Studio 2017,而且(据我所知)编译器具有一些预编译头功能,以及不重新编译未修改函数的功能。但是这些东西目前用处不大,因为大部分逻辑都在在另一个编译单元中将lambda函数转换为普通函数会提高编译时间吗? 我正在研究一个C++服务器项目,它一直在增长着主()/函数,代码基础已经增长到一个点,即使在对主())/>函数进行了一点改动之后,编译时间大约为6分钟(在调试模式下)。(函数的main()大约有5000行长!),c++,templates,lambda,compilation,c++14,C++,Templates,Lambda,Compilation,C++14,我使用的是Visual Studio 2017,而且(据我所知)编译器具有一些预编译头功能,以及不重新编译未修改函数的功能。但是这些东西目前用处不大,因为大部分逻辑都在main()函数中 以下是我的代码(非常简化)版本: struct GrandServer{ std::map<std::string,std::function<void(std::string)>> request; /* some other functions of this ser
main()
函数中
以下是我的代码(非常简化)版本:
struct GrandServer{
std::map<std::string,std::function<void(std::string)>> request;
/* some other functions of this server */
};
int main()
{
SQLClient sql_client;
auto query_database=[&sql_client](auto&& callback){/*stuff*/};
GrandServer server;
server.request["/my_page.html"] = [](std::string&& data){
// Do stuff
};
server.request["/my_page_2.html"] = [](std::string&& data){
// Do more stuff
};
server.request["/my_page_3.html"] = [](std::string&& data){
// Do even more stuff
};
server.request["/my_page_4.html"] = [&query_database](std::string&& data){
// Do many many callbacks
query_database([](std::vector<std::string>&& results){
std::string id = std::move(results.front());
do_something_else([id = std::move(id)](auto&& param) mutable {
/* do more stuff, call more functions that will call back, then answer the client */
});
});
};
/* Many many more lambda functions */
}
虽然这会将main()
的大小减少到可以容忍得多的程度,但我认为这会显著减少编译时间吗?模板实例化的数量不会减少(事实上,我在main()
中引入了一些应该内联的新模板lambda转发器)
还请注意,由于使用move语义回调和捕获变量,将每个逻辑流中的内部lambda函数更改为普通的独立成员或非成员函数并不容易。(模板函数和类不能在单独的编译单元中。)但是,每个逻辑流的长度通常不超过100行,因此我不认为这是必要的
6分钟编译一个大约6000-7000行的代码库似乎太慢了,我认为这是由于我的
main()
函数太长了。我是否应该像上面所描述的那样分解此函数以显著提高此项目的编译时间?您是否已将每个#include
复制到stdfafx.h
??这对减少编译时间有很大帮助。编译器可能会抱怨预编译头太大,但默认大小小得可笑
-Zm选项控制为预编译头分配的量,以兆字节为单位
我已经看到一些项目的编译速度提高了10倍以上
如果将一个网络驱动器映射到一个本地磁盘,有一种简单的方法可以看到编译时间进一步提高3倍
对于这种情况,这里有一个解决方案,它涉及将网络映射替换为注册表中的DOS驱动器。以下是我自己的设置:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]
"R:"="\DosDevices\D:\devel\build"
"S:"="\DosDevices\D:\devel\src"
看起来您真正想要的不是
std::function
,而是void MyServer::*(std::string)>
,或者至少使用指向成员绑定的指针来创建std::function
实例,而不是另一组lambda。也就是说,server.request[“/my\u page.html”]=std::bind(&MyServer::do\u my\u page,&my\u server,\u 1)
@BenVoigt我不希望进行指向成员的指针绑定,因为GrandServer
定义位于外部头文件中。保持它的完整性将允许在有修复时更容易地更新外部头。但是,是的,我认为<代码> STD::绑定< /代码>可能是我想要的。然后您可以考虑<代码>结构> const char路径;无效MyServer::*处理程序(STD:String);} const页面[] = {{ /MyPy.html:“和MyServer::doymiyPope},{…},{}{};后跟(自动和页面:页面)服务器的。请求[page.path]=std::bind(page.handler,&my_服务器,_1)这样,凌乱的绑定调用就不会重复,只会重复每个资源真正不同的部分。页面
定义甚至不需要在main()
中。您是否已将每个#include
复制到`stdfafx.hPutting所有我的include-Windows.h
、标准库、仅外部标题库、我自己的项目标题、,stdafx.h
中包含的所有内容只会将编译时间略微缩短到大约4-5分钟。VS编译器似乎没有抱怨预编译头太大。我的代码都存储在本地机器上,所以我认为有关网络驱动器的部分对我来说无关紧要。
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]
"R:"="\DosDevices\D:\devel\build"
"S:"="\DosDevices\D:\devel\src"