我们的下一个产品已经变得太大,无法在运行32位Windows的计算机上进行链接。所有lib文件的总和超过2Gb,只能在64位Windows机器上链接。最终我们将超越这个边界,因为我们的软件往往增长而不是收缩,我们使用的是32位链接器(MS Visual Studio 2005):当我们的lib总数超过3Gb时,我们预计会遇到麻烦。
如何在不修剪代码的情况下减小.lib文件或.obj文件的大小?例如,我们使用了很多模板:有没有办法减少它们的占用空间?有没有办法找出导致膨胀检查.lib / .obj文件的原因?这可以自动化而不是通过眼睛检查吗? 2.5Gb是很多可以通过比较的文本。
外部约束阻止我们将其作为单个.exe以外的任何内容发布,因此DLL解决方案不可用。
答案 0 :(得分:5)
我曾经参与过一个有几个MLoC的项目。虽然我们仍然会在32位机器上链接,但链接时间非常糟糕并且成为一个主要问题,因为开发人员只能在每个工作日完成十几个编辑 - 编译 - 测试周期。 (通过分布式编译很好地处理了编译时间。)
我们切换到动态链接。这增加了启动时间,但这可以通过延迟加载DLL来管理。
答案 1 :(得分:5)
首先,当然,请确保使用'Optimize for Size'选项进行编译。 如果你这样做,我不希望至少内联对代码大小做出重大贡献。编译器对每个内联候选者进行权衡,以确定与增加代码大小相比有多少(如果有的话)增加代码大小。如果你正在优化大小,编译器不会冒很大的代价。 (请注意,内联非常小的函数实际上可以减少代码大小)
其次,您考虑过unity builds了吗?这几乎完全消除了链接器,并且只有一个转换单元,重复工作要少得多,希望内存占用更小。
最后,我知道Visual Studio(或可能是Windows SDK)有一个64位编译器(也就是说,编译器本身就是一个64位应用程序,而不仅仅是一个生成64位代码的编译器)。考虑使用它。 (我不知道是否还有一个64位链接器)
我不知道链接器是在LARGEADDRESSAWARE标志设置的情况下构建的。如果是这样,在64位计算机上运行它将使进程消耗完整的4GB内存,而不是通常获得的2 GB内存。 (如果需要,您可以通过修改PE头来自己添加标志)
也许限制各种符号的联系也有帮助。如果您知道当前转换单元之外不需要符号,请将其放在匿名命名空间中。这可能允许编译器在将所有内容传递给链接器
之前减少未使用的符号答案 2 :(得分:3)
尝试使用Symbol Sort程序向您显示代码中膨胀的主要位置。另外,只需查看原始.obj文件的大小,就可以合理地了解目标的位置。
答案 3 :(得分:2)
OMFG !!!!!那是huuuuuge!
除了我认为它太大而不合理之外......你不能使用动态链接来避免在编译时链接所有混乱,只在运行时链接什么是必要的(我的意思是,需要加载dll) ?
答案 4 :(得分:2)
是否需要成为一款大应用?
一种选择是将各种模块拆分成DLL并根据需要加载/卸载它们。
或者,您可以使用映射内存拆分多个应用程序并共享数据,管理DBMS甚至是简单的数据文件。
答案 5 :(得分:2)
首先,了解如何测量各种功能使用的大小。不要继续尝试使用替换模板或其他东西,因为你怀疑它会产生重大影响。
运行
dumpbin /HEADERS <somebinary>
找出二进制文件中哪些部分导致巨大的尺寸。你有一个庞大的调试目录部分吗?然后剥离符号。导入地址表大吗?检查表并找到您不需要的符号(模板的问题是模板实例化的符号往往非常大)。可以对异常目录,COM描述符目录等进行类似的分析。
答案 6 :(得分:0)
我认为没有任何一种工具可以为您提供您想要/需要的统计数据。使用带有dumpbin
参数的.map文件或/SYMBOLS
实用程序以及对创建日志的一些后处理可能会帮助您获得所需内容。
如果统计数据证实您怀疑模板膨胀,或者甚至没有确认,那么对源代码做几件事可能是个好主意:
答案 7 :(得分:0)
@hatcat和@jalf:确实有full set of 64bit tools。例如,您可以设置环境变量:
set PreferredToolArchitecture=x64
然后运行Visual Studio(来自de developer console)。
答案 8 :(得分:-1)
我非常怀疑你的实际代码是2GB;你很可能正在编译大量的信息。考虑将一些信息卸载到资源文件中,并将其作为单独步骤嵌入可执行文件中。