代码之家  ›  专栏  ›  技术社区  ›  hatcat

如何让我的大型程序链接?

  •  9
  • hatcat  · 技术社区  · 16 年前

    我们的下一个产品太大,无法在运行32位Windows的计算机上链接。所有lib文件的总和超过2GB,只能在64位Windows计算机上链接。最终,我们将超过这个界限,因为我们的软件倾向于增长而不是收缩,并且我们使用的是32位链接器(MS Visual Studio 2005):当我们的lib总大小超过3GB时,我们预计会遇到麻烦。

    如何在不修剪代码的情况下减小.lib文件或.obj文件的大小?例如,我们使用了很多模板:有没有任何方法可以减少它们的足迹?有没有办法通过检查.lib/.obj文件来找出导致膨胀的原因?这能自动进行而不是用眼睛检查吗?2.5GB是大量的文本,可供浏览和比较。

    外部约束阻止我们以除单个.exe之外的其他方式传送,因此无法使用dll解决方案。

    9 回复  |  直到 8 年前
        1
  •  3
  •   the_mandrill    16 年前

    尝试使用 Symbol Sort 程序显示代码中膨胀的主要部分在哪里。另外,只要查看原始.obj文件的大小,您就可以合理地了解目标位置。

        2
  •  5
  •   sbi    16 年前

    我曾经和几家跨国公司合作过一个项目。虽然我们的系统仍然连接在32位的机器上,但连接时间却非常糟糕,成为了一个主要问题,因为开发人员被减少到每个工作日只能完成十几个编辑编译测试周期。(通过执行分布式编译,编译时间处理得相当好。)

    我们转向了动态链接。这增加了启动时间,但可以通过延迟加载DLL来管理。

        3
  •  5
  •   Community Mohan Dere    9 年前

    首先,当然要确保使用“优化大小”选项进行编译。 如果您这样做,我不会期望内联,至少,对代码大小有很大贡献。编译器权衡了每一个内联候选函数与它提供的性能提升相比,它将增加多少(如果有的话)代码大小。如果您在优化大小,编译器就不会有太多的代码膨胀风险。(注意,内嵌非常小的函数实际上可以减小代码大小)

    第二,你考虑过吗 unity builds ?这几乎完全消除了链接器,而且只有一个翻译单元,那么复制工作就更少了,而且希望内存占用更小。

    最后,我知道Visual Studio(或者可能是Windows SDK)具有64位编译器(也就是说,编译器本身就是64位应用程序,而不仅仅是生成64位代码的编译器)。考虑使用它。(我不知道是否还有64位链接器)

    我不知道链接器是用LargeAddressWare标志集构建的。如果是这样,在64位计算机上运行它将使进程消耗一个完整的4GB内存,而不是它通常获得的2GB内存。(如有必要,您可以通过修改PE头自己添加标志)

    也许限制各种符号之间的联系也会有所帮助。如果知道在当前翻译单元之外不需要符号,请将其放在匿名名称空间中。这可能允许编译器在将所有内容传递给链接器之前修剪未使用的符号。

        4
  •  2
  •   helios    16 年前

    OMFG!!!!!!!那是胡格!

    除此之外,我认为它太大了,不可能是理性的…难道你不能使用动态链接来避免在编译时链接所有混乱的东西,而在运行时只链接那些必要的东西吗(我的意思是,按需加载DLL)?

        5
  •  2
  •   Sliq    16 年前

    它需要成为一个大应用程序吗?

    一种选择是将各种模块拆分为DLL,并根据需要加载/卸载它们。

    或者,您可以拆分为几个应用程序,并使用映射内存共享数据,通过管道传输DBMS,甚至是简单的数据文件。

        6
  •  2
  •   Frerich Raabe    16 年前

    首先,了解如何 测量 各种功能使用的大小。不要继续尝试使用替换模板或其他东西,因为您怀疑这会造成显著的差异。

    跑

    dumpbin /HEADERS <somebinary>
    

    要找出二进制文件中的哪些部分导致了巨大的大小。你有一个巨大的调试目录部分吗?然后去掉符号。导入地址表大吗?检查表格并找到不需要的符号(模板的问题是模板实例化的符号往往非常大)。可以对异常目录、COM描述符目录等进行类似的分析。

        7
  •  0
  •   wilx    16 年前

    我认为没有任何一个工具可以提供你想要/需要的统计数据。使用.map文件或 dumpbin 效用与 /SYMBOLS 参数加上对所创建日志的一些后处理可能会帮助您获得所需的内容。

    如果统计数据证实了您对模板膨胀的怀疑,或者甚至没有得到确认,那么最好对源代码执行以下几项操作:

    1. 尝试使用显式实例化并将模板定义移动到.cpp文件中。当然,只有当您有一组有限且众所周知的类型/值用作模板的参数时,这才有效。
    2. 添加更多抽象和/或间接。不依赖于模板参数的因子代码将其转换为自己的基类或自由函数。如果有多个模板类型参数,请查看是否无法将单个类模板拆分为多个没有重叠模板参数的基类。(见 http://www2.research.att.com/~bs/SCARY.pdf )
    3. 尝试使用pimpl习惯用法;如果可以,避免在头中实例化模板,只在.cpp文件中实例化模板。
    4. 模板很好,但有时普通类也可以工作;例如,如果可以将整型常量作为参数传递给ctor,则避免将整型常量作为非类型模板参数传递。
        8
  •  0
  •   Pablo H    8 年前

    @hatcat和@jalf:确实有一个 full set of 64bit tools . 例如,可以设置环境变量:

    set PreferredToolArchitecture=x64
    

    然后(从开发人员控制台)运行Visual Studio。

        9
  •  -1
  •   Brian    16 年前

    我非常怀疑您的实际代码是2GB;更可能的是您正在编译大量信息。考虑将一些信息卸载到资源文件中,并将其作为单独的步骤嵌入到可执行文件中。