在Visual c++ 2010中使用大型静态数组时编译时间长
Long compile times in Visual C++ 2010 with large static arrays
我们有一个c++项目,其中有几个由预处理工具生成的大型静态数据表(结构体数组)并编译到我们的项目中。到目前为止,我们一直在使用vc++ 2008,但正准备升级到2010,这些数据表的编译时间突然变得很长了。
例如,一个这样的表有大约3,000个条目,每个条目都是一个结构体,包含几个int型和指针,都是静态初始化的。这个文件在vc++ 2008中花了~15秒编译,但在vc++ 2010中需要30 分钟 !作为实验,我尝试将这个表平均分成8个表,每个表都有自己的.cpp文件,每个表的编译时间为20-30秒。这让我认为编译器内部的某些东西在这些表的长度中是O(n^2)。
cl.exe的内存使用稳定在400 MB左右(我的机器有12 GB的RAM),并且我没有看到任何I/O活动一旦它稳定,所以我相信这不是磁盘缓存问题。
有人知道这里可能发生了什么吗?是否有一些编译器功能,我可以关闭以恢复正常的编译时间?
下面是表格中数据的示例:
// 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,
},
如您所见,它包括各种int和enum以及一些字面值字符串、函数指针和指向其他静态数据表的指针。
可能值得关闭这个文件的所有优化(它不会给你买任何东西),以防它是优化器的N^2。
我也遇到过同样的问题。有一个包含大约40,000个元素的const数据数组。编译时间大约是15秒。当我从"const uint8_t pData[] ={…}"到"静态 const uint8_t pData [] = { ...}"编译时间下降到不到1秒。
我曾见过(不记得在哪里)一种将大型静态数据直接转换为目标文件的技术。然后,c++代码将数组声明为extern
,链接器将两者匹配在一起。这样,数组数据根本不会经历编译步骤。
Microsoft C/c++工具CVTRES.exe
也基于类似的原理,但它不生成符号,而是生成一个单独的资源部分,需要特殊的api来访问(FindResource
, LoadResource
, LockResource
)。
啊,这是我记得找到的一个工具:bin2coff
作者有一大堆相关的工具
或者,您可以尝试减少依赖关系,这样特定的源文件就永远不需要重新编译。然后,最小重建将自动使用现有的.obj文件。甚至可以将。obj文件检查到源代码控制中
您可以尝试在C/c++设置中关闭纯MISL CLR支持。
尝试使您的数组静态const,这减少了编译时间(但不是文件大小),在类似的情况下,我已经看到了无形的
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 静态数组的自由动态数组
- 如何在C++函数中声明静态 2D 数组?
- 从另一个静态常量数组初始化静态常量数组(只需少量计算)
- 基于字节数组生成静态范围整数值
- 如何在C++中删除静态数组?
- 为什么 &a 和 c++ 中的静态数组相同?
- 为什么静态数组成员变量在调用对象的实例后不显示任何内容?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 将在堆栈上声明的元素添加到静态数组
- const_cast静态数组以添加恒常性
- C++访问静态 constexpr 数组
- 初始化类中的静态 const 数组 - C++
- 将静态字符数组中的字符分配给动态分配的字符数组 - 访问冲突
- 动态分配的数组和静态数组之间的区别
- 如何在 C++ 中使用 NULL(或 0)初始化静态字符数组
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 我可以使用 constexpr 函数声明一个静态数组吗?
- 如何在静态函数中使用成员函数数组
- 具有大的2d数组:静态int与int