为什么C++的链接几乎不使用CPU?

28

在一个本地的C++项目中,链接现在需要一到两分钟的时间。然而,在此期间,CPU的使用率从编译时的 100% 下降到几乎为零。这是否意味着链接主要是磁盘活动?

如果是这样,SSD会对这产生很大的影响吗?但是,为什么不将所有OBJ文件(或尽可能多的OBJ文件)保存在编译后的内存中,以避免这种情况发生?有 4 GB 的 RAM 应该能够节省大量的磁盘访问,并使其再次成为 CPU 密集型任务,对吧?

更新: 因此,显而易见的后续问题是,VC++编译器和链接器是否可以更好地互相通信以优化流程并将 OBJ 文件保存在内存中,类似于 Delphi 是如何做的?


我猜测这是由操作系统缓存到RAM中来避免这种情况发生,如果有足够的RAM来完成编译,那么操作系统会这样做。由于编译需要大量的RAM,这可能会导致操作系统将OBJ文件刷新到磁盘上。如果你强制让它保持OBJ文件在内存中以使链接更快,那么很可能会使编译速度变得更慢。 - Mooing Duck
5个回答

14

链接确实是一项基于磁盘的活动。Borland Pascal(早期)会将整个程序保留在内存中,这就是为什么它能够如此快速地进行链接。

你的OBJ文件没有保存在RAM中,因为编译器和链接器是独立的程序。如果你的开发环境有一个集成的编译器和链接器(而不是作为单独的进程运行),它确实可以将所有内容保存在RAM中。

但是你会失去将开发环境与编译器和/或链接器分离的能力-你必须使用相同的编译器/链接器,并且无法在环境外运行编译器。


我以为可能会,但由于 Delphi 的各种不同版本,我不确定它是否仍然有效。 - Eric Brown
4
如果您正在运行任何合理的操作系统,信息已经被缓存在内存中,减少了需要将整个对象集在内存中进行链接的必要性。 - Billy ONeal
我已经在XP、Vista和W7上运行了它,看起来并没有太大的区别。我不认为W7提供任何查看正在RAM缓存的文件的方法? - Mr. Boy
1
obj和尤其是pdb文件通常非常大,根本无法适应内存(至少不能适应内存系统愿意用作缓存的部分)。 - Suma
当我构建时,我不相信我会最终得到4Gb的临时文件...如果是这样的话,那么几年前我会一直用完磁盘空间。此外,Windows可以使用它所拥有的,并且在包含VM时具有近乎无限的内存。 - Mr. Boy

7
你可以尝试安装一些RAM磁盘实用工具,并将你的obj目录放在RAM磁盘上,甚至整个项目目录都可以。这样应该会显著提高速度。之后不要忘记使其永久化。:-D

值得一试...我认为你可以将中间文件设置到某个单独的位置,这样它就不需要永久存在,除非ONJ文件丢失,否则你每次都需要进行完整的构建。不确定这是否值得麻烦,这取决于RAM磁盘在自动化所有这些方面有多大帮助。 - Mr. Boy

6
在Visual Studio的调试版本中,您可以使用增量链接,这样通常可以避免花费大量时间进行链接。基本上意味着,它不会从头开始链接整个EXE(或DLL)文件,而是建立在您上次链接的基础上,并仅替换更改的内容。
但是,这对于发布版本不推荐使用,因为它会增加运行时开销,并可能导致EXE文件比通常大数倍。

2
抱歉,不回答该问题。 - Byron Whitlock
它确实解决了在链接性能方面进行“重大更改”的问题。 - shoosh
他问SSD是否会加速链接速度,如果它是IO限制的话。 - Byron Whitlock
5
提供替代方法和直接回答字面意思的问题同样有效(除非该问题表明曾考虑并放弃了替代方法)。 - Ben Voigt
我认为增量链接(/Gm?)是一个有效的答案。不幸的是,我还是关闭了它,转而使用/MP(多线程编译),以更好地利用我的核心。 - Mr. Boy

6
Visual Studio的链接器主要受I/O限制,但具体程度取决于几个变量。
1. 增量链接(在Debug版本中常见)通常需要较少的I/O。
2. 写入PDB文件(用于符号)可能会占用大量时间。这是Microsoft在VS 2010中针对的特定瓶颈。现在,PDB写入是异步完成的。我没有尝试过,但听说可以显著提高链接时间。
3. 如果使用链接时代码生成(LTCG)(在Release版本中常见),则一开始有所有通常的I/O。然后,链接器重新调用编译器为可以进一步优化的部分重新生成代码。这部分通常更加CPU密集。我不确定链接器是否实际上会在单独的进程中启动编译器并等待(在这种情况下,您仍将看到链接器进程的低CPU使用率),还是编译是在链接器进程中完成的(在这种情况下,您将看到链接器经历重I/O和重CPU的阶段)。
使用SSD可以帮助解决I/O限制的问题。拥有第二个驱动器也可以帮助。例如,如果您的源代码和对象都在一个驱动器上,并将PDB写入单独的驱动器,则链接器应花费更少的时间等待PDB编写器。拥有第二个旋转驱动器极大地提高了我们当前团队的链接时间。

+1. 从传统的机械硬盘转换到固态硬盘可以极大地提高大多数构建过程的速度。这种速度提升通常需要亲眼看到才能相信 :-). - Mike Clark

3

不知道链接器与操作系统的交互方式,很难说是什么导致了链接器运行如此缓慢。幸运的是,微软提供了进程监视器,可以帮助你解决这个问题。

即使没有源代码,它也能帮助我诊断Visual Studio IDE和调试器中的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接