我正在研究一个受到不断增长的main()函数困扰的C服务器项目,并且代码库已经发展到编译时间大约为6分钟的时间点(在调试模式下),即使我稍微改变了一下主功能. (main()函数大约5000行!)
我正在使用Visual Studio 2017,并且(据我所知)编译器具有一些预编译的头功能,以及不重新编译未修改函数的功能.但是这些东西目前用处不大,因为大部分逻辑都在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()函数中,通过定义存储在std :: map中的lambdas. lambda函数包含几个级别的lambda函数,主要是从数据库定义(异步)回调.其他独立函数主要包括GrandServer中的函数以及各种实用程序函数(例如时间转换,异步回调实用程序,unicode实用程序等),但它们都不构成应用程序的核心逻辑.这感觉就像非常糟糕的代码蔓延:(
我正在考虑将所有顶级lambda(即直接存储在server.request中的那些)转换为普通的独立成员函数到几个单独的编译单元中,如下所示:
// split definitions of methods in this class over several compilation units
// header file left out for brevity
struct MyServer{
SQLClient sql_client;
void query_database=[this](auto&& callback){/*stuff*/};
void do_my_page(std::string&& data){
// Do stuff
}
void do_my_page_2(std::string&& data){
// Do stuff
}
void do_my_page_3(std::string&& data){
// Do stuff
}
void do_my_page_4(std::string&& data){
// Do many many callbacks
query_database([](std::vector<int>&& results){
do_something_else([](auto&& param){
/* do more stuff, call more functions that will call back, then answer the client */
});
});
}
};
// main.cpp
struct GrandServer{
std::map<std::string,std::function<void(std::string)>> request;
/* some other functions of this server */
};
int main()
{
GrandServer server;
MyServer my_server;
server.request["/my_page.html"] = [&my_server](auto&&... params){my_server.do_my_page(std::forward<decltype(params)>(params)...);};
server.request["/my_page_2.html"] = [&my_server](auto&&... params){my_server.do_my_page_2(std::forward<decltype(params)>(params)...);};
server.request["/my_page_3.html"] = [&my_server](auto&&... params){my_server.do_my_page_3(std::forward<decltype(params)>(params)...);};
server.request["/my_page_4.html"] = [&my_server](auto&&... params){my_server.do_my_page_4(std::forward<decltype(params)>(params)...);};
/* Lots more lambda functions */
}
虽然这会将main()的大小减小到更容易忍受的程度,但我是否应该期望这会显着减少编译时间?模板实例化的数量不会减少(实际上,我在main()中引入了一些应该内联的新模板lambda转发器).
另请注意,由于回调和使用移动语义捕获变量,将每个逻辑流中的内部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"