如何使Windows与Linux一样快速地编译C++?

gma*_*man 139 linux windows performance compilation

我知道这不是一个编程问题,而是相关的.

我在一个相当大的跨平台项目上工作.在Windows上我使用VC++ 2008.在Linux上我使用gcc.项目中有大约40k个文件.在编译和链接同一个项目时,Windows比Linux慢10到40倍.我该如何解决这个问题?

单个更改增量构建在Linux上为20秒,在Windows上为> 3分钟.为什么?我甚至可以在Linux中安装'gold'链接器,并将时间缩短到7秒.

同样,git在Linux上比Windows快10到40倍.

在git的情况下,git可能不是以最佳方式使用Windows而是使用VC++?你认为微软希望让自己的开发人员尽可能高效,而更快的编译将会有很长的路要走.也许他们试图鼓励开发人员加入C#?

作为简单的测试,找到一个包含大量子文件夹的文件夹并做一个简单的操作

dir /s > c:\list.txt
Run Code Online (Sandbox Code Playgroud)

在Windows上.执行两次并在第二次运行时间,以便从缓存中运行.将文件复制到Linux并执行等效的2次运行并在第二次运行时运行.

ls -R > /tmp/list.txt
Run Code Online (Sandbox Code Playgroud)

我有2个工作站具有完全相同的规格.HP Z600s配备12gig内存,8个内核,3.0ghz.在包含~400k文件的文件夹上,Windows需要40秒,Linux需要<1秒.

我可以设置一个注册表设置来加速Windows吗?是什么赋予了?


一些与编译时间相关的略微相关的链接,不一定是i/o.

Nou*_*him 32

除非硬核Windows系统黑客出现,否则你不会得到超过党派评论(我不会做)和猜测(这是我将要尝试的).

  1. 文件系统 - 您应该在同一文件系统上尝试相同的操作(包括dir).我碰到其中基准的几个文件系统的各种参数.

  2. 缓存.我曾经尝试在RAM磁盘上运行Linux上的编译,并发现它比在磁盘上运行要慢,这要归功于内核处理缓存的方式.这是Linux的一个重要卖点,可能是性能如此不同的原因.

  3. Windows上的依赖规范不良.也许Windows的铬依赖规范不如Linux正确.当您进行小的更改时,这可能会导致不必要的编译.您可以在Windows上使用相同的编译器工具链对此进行验证.

  • 如果将一块内存分配为ramdisk,则内核无法进行缓存或用于其他任何内容.实际上,你正绞尽力量并强迫它为自己的算法使用更少的内存.我的知识是经验性的.当我使用RAMdisk进行编译时,我失去了性能. (2认同)

Ric*_*kNZ 28

一些想法:

  1. 禁用8.3名称.这可能是具有大量文件和相对较少数量的文件夹的驱动器的一个重要因素:fsutil behavior set disable8dot3 1
  2. 使用更多文件夹.根据我的经验,NTFS开始变慢,每个文件夹超过1000个文件.
  3. 使用MSBuild启用并行构建; 只需添加"/ m"开关,它将自动为每个CPU核心启动一份MSBuild.
  4. 将您的文件放在SSD上 - 对随机I/O有很大帮助.
  5. 如果平均文件大小远大于4KB,请考虑使用较大的簇大小重建文件系统,该大小大致与平均文件大小相对应.
  6. 确保文件已经过碎片整理.碎片文件会导致大量磁盘搜索,这会使您的吞吐量降低40倍.使用sysinternals中的"contig"实用程序或内置的Windows碎片整理程序.
  7. 如果您的平均文件大小很小,并且您所在的分区相对较大,则可能是您使用碎片MFT运行,这对性能有害.此外,小于1K的文件直接存储在MFT中.上面提到的"contig"实用程序可以提供帮助,或者您可能需要增加MFT大小.以下命令将其加倍,达到音量的25%:fsutil behavior set mftzone 2将最后一个数字更改为3或4,以增加12.5%的增量.运行该命令后,重新启动,然后创建文件系统.
  8. 禁用上次访问时间: fsutil behavior set disablelastaccess 1
  9. 禁用索引服务
  10. 禁用您的防病毒和反间谍软件,或至少设置相关文件夹被忽略.
  11. 将文件放在与操作系统和页面文件不同的物理驱动器上.使用单独的物理驱动器允许Windows对两个驱动器使用并行I/O.
  12. 看看你的编译器标志.Windows C++编译器有很多选项; 确保你只使用你真正需要的那些.
  13. 尝试增加操作系统用于页面缓冲池缓冲区的内存量(确保首先有足够的RAM): fsutil behavior set memoryusage 2
  14. 检查Windows错误日志以确保您没有遇到偶尔的磁盘错误.
  15. 查看与物理磁盘相关的性能计数器,以查看磁盘的繁忙程度.每次传输的高队列长度或长时间都是不好的迹象.
  16. 在原始传输时间方面,前30%的磁盘分区比磁盘的其余部分快得多.较窄的分区也有助于减少寻道时间.
  17. 你在使用RAID吗?如果是这样,您可能需要优化您对RAID类型的选择(RAID-5对于编写重量级操作(如编译)不利)
  18. 禁用您不需要的任何服务
  19. 碎片整理文件夹:将所有文件复制到另一个驱动器(只是文件),删除原始文件,将所有文件夹复制到另一个驱动器(只是空文件夹),然后删除原始文件夹,对原始驱动器进行碎片整理,首先复制文件夹结构,然后复制文件.当Windows一次创建一个文件的大文件夹时,文件夹最终会碎片化并且速度很慢.("重叠群"也应该在这里帮助)
  20. 如果您受I/O限制并且备用CPU周期,请尝试打开磁盘压缩.它可以为高度可压缩的文件(如源代码)提供一些显着的加速,但在CPU中有一些成本.

  • 我们需要一个更好的基准.测量枚举文件夹所需的时间不是一个非常有用的IMO.NTFS针对具有btree结构的单文件查找时间进行了优化.在Linux(最后我看过)中,应用程序可以通过单个系统调用读取整个文件夹,并完全在用户代码中迭代生成的结构; Windows需要为每个文件单独进行sys调用.无论哪种方式,编译器都不需要读取整个文件夹.... (6认同)
  • 那么你所描述的正是问题所在.选择不同的基准并没有解决问题 - 你只是看着别处. (3认同)
  • 问题是关于优化编译时间。文件夹枚举时间不会在Windows上占据编译时间,即使文件夹中有成千上万个文件也是如此。 (2认同)

Age*_*t_L 25

NTFS每次都会保存文件访问时间.你可以尝试禁用它:"fsutil behavior set disablelastaccess 1"(重启)

  • 测试比之前的36秒减少了4秒.与我的linux VM上的.6秒相比仍然可恶 (6认同)

小智 21

就我所知,visual c ++的问题是编译器团队优先考虑这种情况不是优先事项.他们的解决方案是您使用他们的预编译头功能.这是Windows特定项目所做的.它不便携,但它的工作原理.

此外,在Windows上,您通常有病毒扫描程序,以及系统还原和搜索工具,如果他们为您监视您的buid文件夹,可能会完全破坏您的构建时间.Windows 7资源监视器可以帮助您发现它.我在这里回复了一些优化vc ++构建时间的进一步提示,如果你真的感兴趣的话.


bfr*_*rog 17

我个人发现在linux上运行一个Windows虚拟机设法消除了Windows中的大量IO缓慢,可能是因为linux vm正在进行大量的缓存,而Windows本身并没有.

这样做我能够加快我从事的大型(250Kloc)C++项目的编译时间,从15分钟到大约6分钟.

  • 我使用在Windows 7工作站内运行的Ubuntu 11.04 VM测试了上面的场景.linux VM为0.6秒,Windows工作站为36秒 (8认同)
  • 如果您使用虚拟机并设置共享驱动器,您实际上可以免费加速编译. (2认同)

Tom*_*ime 16

这样做的困难在于C++倾向于在许多小的,单独的文件上传播自己和编译过程.这是Linux擅长的东西,Windows不是.如果您想为Windows制作一个非常快速的C++编译器,请尝试将所有内容保存在RAM中并尽可能少地触摸文件系统.

这也是你如何建立一个更快的Linux C++编译链,但它在Linux中不那么重要,因为文件系统已经为你做了很多调整.

其原因在于Unix文化:从历史上看,Unix世界中的文件系统性能优先于Windows.并不是说它在Windows中不是优先考虑的问题,只是在Unix中它是一个更高的优先级.

  1. 访问源代码.

    你不能改变你无法控制的东西.缺乏对Windows NTFS源代码的访问意味着尽管硬件改进,但大多数提高性能的努力仍然存在.也就是说,如果性能很慢,您可以通过改进硬件来解决问题:总线,存储介质等.如果你必须解决问题而不是解决它,你只能这么做.

    访问Unix源代码(甚至在开源之前)更为普遍.因此,如果您想提高性能,您可以先在软件中使用(更便宜,更简单),然后再使用硬件.

    因此,世界上有许多人通过研究Unix文件系统并找到提高性能的新方法获得了博士学位.

  2. Unix倾向于许多小文件; Windows倾向于少数(或单个)大文件.

    Unix应用程序倾向于处理许多小文件.想想软件开发环境:许多小的源文件,每个文件都有自己的用途.最后阶段(链接)会创建一个大文件,但这个比例很小.

    因此,Unix具有高度优化的系统调用,用于打开和关闭文件,扫描目录等.Unix研究论文的历史跨越了数十年的文件系统优化,这些优化在改进目录访问(查找和全目录扫描),初始文件打开等方面投入了大量精力.

    Windows应用程序倾向于打开一个大文件,长时间保持打开状态,完成后关闭它.想想MS-Word.msword.exe(或其他)打开文件一次并附加几个小时,更新内部块,等等.优化文件打开的价值将是浪费时间.

    Windows基准测试和优化的历史记录是人们可以读取或写入长文件的速度.这是优化的.

    可悲的是,软件开发趋向于第一种情况.哎呀,Unix最好的文字处理系统(TeX/LaTeX)鼓励你把每一章放在一个不同的文件中,并将它们全部#include.

  3. Unix专注于高性能; Windows专注于用户体验

    Unix在服务器机房开始:没有用户界面.用户唯一看到的就是速度.因此,速度是一个优先事项.

    Windows在桌面上启动:用户只关心他们看到的内容,他们会看到UI.因此,在改进UI方面花费的能量超过了性能.

  4. Windows生态系统取决于计划的过时.为什么在新硬件只需一两年的时间内优化软件?

    我不相信阴谋论,但如果我这样做,我会指出,在Windows文化中,提高绩效的动机较少.Windows商业模式取决于人们购买钟表机构等新机器.(这就是为什么如果MS推迟运行操作系统或英特尔错过芯片发布日期,数千家公司的股价会受到影响.)这意味着通过告诉人们购买新硬件来激励解决性能问题; 而不是通过改善真正的问题:缓慢的操作系统.Unix来自学术界,预算紧张,你可以通过发明一种新的方法来提高文件系统的速度,从而获得博士学位; 学术界很少有人通过发出采购订单获得积分来解决问题.在Windows中,没有阴谋使软件保持缓慢,但整个生态系统依赖于计划的过时.

    此外,由于Unix是开源的(即使不是,每个人都可以访问源代码),任何无聊的博士生都可以阅读代码,并通过使其变得更好而成名.这种情况在Windows中不会发生(MS确实有一个程序可以让学者访问Windows源代码,很少被利用).看看这些与Unix相关的性能论文的选择:http://www.eecs.harvard.edu/margo/papers/或查看Osterhaus,Henry Spencer或其他人的论文历史.哎呀,在Unix历史上最大的(也是最值得关注的)辩论之一就是Osterhaus和Selzer之间的来回http://www.eecs.harvard.edu/margo/papers/usenix95-lfs/supplement/rebuttal. html的 你看不到那种在Windows世界上发生的事情.你可能会看到供应商互相支持,但最近似乎更为罕见,因为创新似乎都处于标准体系层面.

这就是我看到它的方式.

更新: 如果你看看微软推出的新编译器链,你会非常乐观,因为他们正在做的很多事情使得更容易将整个工具链保留在RAM中并重复工作量减少.非常令人印象深刻

  • 说原因是"文化而不是技术"并不能真正回答这个问题.显然,有一个或多个潜在的技术原因导致某些操作在Windows上比在Linux上慢.现在,文化问题可以解释为什么人们做出技术决定; 但这是一个技术问答网站.答案应该涵盖为什么一个系统比另一个系统慢(以及可以采取哪些措施来改善这种情况)的*技术*原因,而不是关于文化的无可争议的推测. (6认同)

MSN*_*MSN 7

增量链接

如果将VC 2008解决方案设置为具有.lib输出的多个项目,则需要设置"使用库依赖项输入"; 这使链接器直接链接到.obj文件而不是.lib.(实际上它会逐渐增加链接.)

目录遍历性能

比较原始计算机上的目录爬网与将新创建的目录与另一台计算机上的相同文件进行爬网有点不公平.如果要进行等效测试,则应该在源计算机上创建另一个目录副本.(它可能仍然很慢,但这可能是由于任何数量的事情:磁盘碎片,短文件名,后台服务等)虽然我认为perf问题dir /s更多地与编写输出而不是测量实际文件遍历表现.dir /s /b > nul使用庞大的目录,我的机器上的速度也很慢.


Áti*_*ves 6

我很确定它与文件系统有关.我从事Linux和Windows的跨平台项目,其中所有代码都很常见,除非绝对需要依赖于平台的代码.我们使用Mercurial,而不是git,因此git的"Linuxness"不适用.与Linux相比,从中央存储库中获取更改需要永远在Windows上,但我不得不说我们的Windows 7机器比Windows XP机器做得好很多.在VS 2008之后编译代码甚至更糟.它不仅仅是hg; CMake在Windows上的运行速度也慢得多,而且这两种工具都比其他任何工具都使用文件系统.

问题是如此糟糕,以至于大多数在Windows环境中工作的开发人员都不再费心去做增量构建了 - 他们发现做一个统一构建的速度更快.

顺便说一句,如果你想在Windows中大幅提高编译速度,我建议上面提到的统一版本.在构建系统中正确实现是很痛苦的(我在CMake中为我们的团队做过),但一旦完成,我们的持续集成服务器就会自动加速.根据构建系统吐出的二进制数量,您可以获得1到2个数量级的改进.你的旅费可能会改变.在我们的例子中,我认为它加快了Linux构建三倍,而Windows大约加倍了10倍,但是我们有很多共享库和可执行文件(这降低了统一构建的优势).


V15*_*I0N 5

您如何构建大型跨平台项目?如果你在Linux和Windows上使用常见的makefile,如果makefiles的设计速度不快,那么你可以轻松地将Windows性能降低10倍.

我刚刚使用针对Linux和Windows的通用(GNU)makefile修复了一些跨平台项目的makefile.Make正在sh.exe为配方的每一行开始一个过程,导致Windows和Linux之间的性能差异!

根据GNU make文档

.ONESHELL:

应解决此问题,但Windows make不支持此功能(目前).因此,将配方重写为单个逻辑行(例如,通过在当前编辑行的末尾添加; \或\)非常有效!