【问题标题】:Why does C++ linking use virtually no CPU?为什么 C++ 链接几乎不使用 CPU?
【发布时间】:2011-02-14 00:32:44
【问题描述】:

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

如果是这样,这是 SSD 会做出重大改变的主要领域吗?但是,为什么编译后我的所有 OBJ 文件(或尽可能多的文件)没有保存在 RAM 中以避免这种情况?有了 4 GB 的 RAM,我应该能够节省大量磁盘访问并再次使其受 CPU 限制,不是吗?

更新:所以显而易见的后续是,可以 VC++ 编译器和链接器更好地一起交谈,以简化事情并将 OBJ 文件保存在内存中,类似于 @ 987654321@是吗?

【问题讨论】:

  • 推测它留给操作系统将它们缓存在 RAM 中以避免这种情况,如果在编译时有足够的 RAM 可以这样做,它就会这样做。由于编译需要大量 RAM,这可能会导致操作系统将 OBJ 文件刷新到磁盘。如果你强制它将 OBJ 文件保存在内存中以加快链接速度,那么它可能会使编译速度仍然慢得多。

标签: c++ visual-c++ linker compilation


【解决方案1】:

链接确实主要是基于磁盘的活动。 Borland Pascal(过去)会将整个程序保存在内存中,这就是它链接速度如此之快的原因。

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

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

【讨论】:

  • 我认为它可能,但随着 Delphi 的各种化身,我不确定它是否仍然如此。
  • 如果您在任何合理的操作系统上运行,信息将已经缓存在内存中,从而减少了将整个对象设置在内存中以进行链接的需要。
  • 我已经在 XP、Vista 和 W7 上运行过它,但似乎并没有太大的不同。我不认为 W7 提供任何方法来查看哪些文件正在被 RAM 缓存?
  • obj 尤其是 pdb 文件通常很大,根本放不下内存(至少放不下内存系统愿意用作缓存的部分)。
  • 我不相信我在构建时最终会得到 4Gb 的临时文件......如果我在几年前这样做的话,我会一直用完磁盘空间。此外,Windows 可以使用它所拥有的内存,并且在包含 VM 的情况下拥有近乎无限的内存。
【解决方案2】:

您可以尝试安装其中一些 RAM 磁盘实用程序,并将您的 obj 目录保留在 RAM 磁盘甚至整个项目目录上。这应该会大大加快速度。

之后别忘了让它永久化:-D

【讨论】:

  • 值得一试...我认为您可以将中间文件设置为单独的某个地方,这样它就不需要是永久的,除非如果 ONJ 文件去,您必须完整一直在构建。不确定是否值得麻烦,这取决于 RAM 磁盘在自动化所有这些方面的帮助程度
【解决方案3】:

Visual Studio 链接器主要受 I/O 限制,但具体程度取决于几个变量。

  1. 增量链接(在调试版本中很常见)通常需要更少的 I/O。

  2. 编写 PDB 文件(用于符号)会消耗大量时间。这是微软在 VS 2010 中针对的特定瓶颈。PDB 写入现在是异步完成的。我没有尝试过,但我听说它可以帮助链接时间。

  3. 如果您使用链接时代码生成 (LTCG)(在发布版本中很常见),您最初拥有所有常用的 I/O。然后,链接器重新调用编译器为可以进一步优化的部分重新生成代码。这部分通常是 CPU 密集型的。顺便说一句,我不知道链接器是否真的在单独的进程中启动编译器并等待(在这种情况下,您仍然会看到链接器进程的 CPU 使用率很低),或者编译是否在链接器进程中完成(在这种情况下,您会看到链接器经历了重 I/O 阶段,然后是重 CPU 阶段)。

使用 SSD 有助于处理 I/O 绑定部分。简单地拥有第二个驱动器也可以提供帮助。例如,如果您的源和对象都在一个驱动器上,并且您将 PDB 写入单独的驱动器,则链接器应该花更少的时间等待 PDB 写入器。拥有第二个旋转驱动器极大地帮助了我当前团队的链接时间。

【讨论】:

  • +1。从旋转盘片迁移到 SSD 可以对大多数构建过程的速度产生令人难以置信的影响。速度提升通常必须被认为是可信的:-)。
【解决方案4】:

在 Visual Studio 的调试版本中,您可以使用incremental linking,这通常可以避免大量时间花在链接上。基本上,这意味着它不是从头开始链接整个 EXE(或 DLL)文件,而是建立在您上次链接的文件的基础上,只替换更改的内容。

但是,不建议将这用于发布版本,因为它会在运行时增加一些开销,并可能导致 EXE 文件比通常大几倍。

【讨论】:

  • 抱歉,没有解决问题。
  • 它确实解决了在链接性能方面做出“重大改变”的问题。
  • 嗯?他问如果ssd是io绑定的,是否会加快链接速度。
  • 提供替代方法与回答字面问题一样有效(除非问题表明替代方法已被考虑并放弃)。
  • 我认为增量链接 (/Gm?) 是一个有效的答案。遗憾的是,无论如何我都将其关闭以支持 /MP(多线程编译)以更好地使用我的内核。
【解决方案5】:

如果不知道它是如何与操作系统交互的,很难说到底是什么让链接器花费了这么长时间。值得庆幸的是,Microsoft 提供了Process Monitor,因此您可以做到这一点。

它帮助我在无需访问源代码的情况下使用 Visual Studio IDE 和调试器诊断错误。

【讨论】:

    猜你喜欢
    • 2012-12-23
    • 2023-01-17
    • 2011-01-05
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2011-01-18
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多