我们有一个C ++项目,其中有一些由预处理工具生成并编译到我们项目中的大型静态数据表(结构数组)。到目前为止,我们一直在使用VC ++ 2008,但是准备进入2010年,这些数据表突然需要很长时间才能编译。
作为一个例子,一个这样的表有大约3,000个条目,每个条目都是一个包含几个整数和指针的结构,所有这些都是静态初始化的。这个文件在VC ++ 2008中编译需要大约15秒,但在VC ++ 2010中需要30分钟分钟!
作为一项实验,我尝试将此表均匀地分成8个表,每个表都在自己的.cpp文件中,并且每个表在20-30秒内编译。这让我觉得编译器内部的东西在这些表的长度上是O(n ^ 2)。
cl.exe平台的内存使用量大约为400 MB(我的机器有12 GB的RAM),一旦它处于高位状态,我看不到任何I / O活动,所以我认为这不是磁盘缓存问题。 / p>
有没有人知道这里会发生什么?是否有一些编译器功能可以关闭以恢复正常的编译时间?
以下是表中数据的示例:
// cid (0 = 0x0)
{
OID_cid,
OTYP_Cid,
0 | FOPTI_GetFn,
NULL,
0,
NULL,
(PFNGET_VOID) static_cast<PFNGET_CID>(&CBasic::Cid),
NULL,
CID_Basic,
"cid",
OID_Identity,
0,
NULL,
},
// IS_DERIVED_FROM (1 = 0x1)
{
OID_IS_DERIVED_FROM,
OTYP_Bool,
0 | FOPTI_Fn,
COptThunkMgr::ThunkOptBasicIS_DERIVED_FROM,
false,
NULL,
NULL,
NULL,
CID_Basic,
"IS_DERIVED_FROM",
OID_Nil,
0,
&COptionInfoMgr::s_aFnsig[0],
},
// FIRE_TRIGGER_EVENT (2 = 0x2)
{
OID_FIRE_TRIGGER_EVENT,
OTYP_Void,
0 | FOPTI_Fn,
COptThunkMgr::ThunkOptBasicFIRE_TRIGGER_EVENT,
false,
NULL,
NULL,
NULL,
CID_Basic,
"FIRE_TRIGGER_EVENT",
OID_Nil,
0,
NULL,
},
// FIRE_UNTRIGGER_EVENT (3 = 0x3)
{
OID_FIRE_UNTRIGGER_EVENT,
OTYP_Void,
0 | FOPTI_Fn,
COptThunkMgr::ThunkOptBasicFIRE_UNTRIGGER_EVENT,
false,
NULL,
NULL,
NULL,
CID_Basic,
"FIRE_UNTRIGGER_EVENT",
OID_Nil,
0,
NULL,
},
如您所见,它包括各种整数和枚举,以及一些文字字符串,函数指针和指向其他静态数据表的指针。
答案 0 :(得分:6)
可能值得关闭此文件的所有优化(无论如何都不会给你买任何东西),以防它是N ^ 2的优化器。
答案 1 :(得分:4)
我遇到了同样的问题。有一个const数组,有大约40'000个元素。编译时间约为15秒。当我从“const uint8_t pData [] = {...}”更改为“ static const uint8_t pData [] = {...}时”编译时间不到1秒。< / p>
答案 2 :(得分:1)
我已经看到(不记得在哪里)将大型静态数据直接转换为目标文件的技术。然后,您的C ++代码将数组声明为extern
,并且链接器将两者匹配在一起。这样,数组数据根本就不会经历编译步骤。
Microsoft C / C ++工具CVTRES.exe
遵循类似的原则,但它不生成符号,而是需要特殊API才能访问的单独资源部分(FindResource
,{{1} },LoadResource
)。
啊,这是我记得找到的工具之一:bin2coff
作者有a whole bunch of related tools
或者,您可以尝试减少依赖项,以便特定的源文件永远不需要重新编译。然后最小重建将自动使用现有的.obj文件。甚至可以将.obj文件检查到源代码管理中。
答案 3 :(得分:1)
您可以尝试在C / C ++设置中关闭Pure MISL CLR支持。为我工作。
答案 4 :(得分:0)
尝试使你的数组成为静态const,这减少了编译时间(但不是文件大小),在类似的情况下,我已经看到了无形的。