与旧版本相比,CMake在生成Makefiles阶段的速度慢了3.16个数量级

与旧版本相比,CMake在生成Makefiles阶段的速度慢了3.16个数量级,makefile,cmake,strace,callgrind,Makefile,Cmake,Strace,Callgrind,我正在咨询一家公司如何加快他们的构建速度,我立即向他们指出了预编译的头文件和unity构建——10分钟的完整构建可以轻松减少到2-3分钟。幸运的是CMake 3.16最近发布了,所以我告诉他们升级 问题在于:一旦他们从CMake 2.6切换到3.16,运行CMake所需的时间从大约20秒跳到了10分钟以上。大部分时间都花在生成阶段。如果您给它足够的时间,并且使用unity builds成功编译了代码,那么它确实会成功完成,但是这个CMake时间是不可接受的 以下是他们的设置: CMake 2.

我正在咨询一家公司如何加快他们的构建速度,我立即向他们指出了预编译的头文件和unity构建——10分钟的完整构建可以轻松减少到2-3分钟。幸运的是CMake 3.16最近发布了,所以我告诉他们升级

问题在于:一旦他们从CMake 2.6切换到3.16,运行CMake所需的时间从大约20秒跳到了10分钟以上。大部分时间都花在生成阶段。如果您给它足够的时间,并且使用unity builds成功编译了代码,那么它确实会成功完成,但是这个CMake时间是不可接受的

以下是他们的设置:

  • CMake 2.6,带有全局标志/定义/包含的旧式CMake-非现代(基于目标)。没什么特别的-没有自定义命令或构建规则&复杂的依赖关系
  • 使用的编译器是GCC 7,它们生成Makefiles-操作系统是CentOS 7,内核:Linux3.10.0-862.14.4.el7.x8664
  • 大约2000个
    .cpp
    文件分布在100个库和600个可执行文件中(其中大多数是测试可执行文件,其中只有一个
    .cpp
  • 大多数
    .cpp
    文件都是通过以下方式收集/整合的-我们知道没有明确列出
    .cpp
    文件是一种反模式,但这不是重点-我认为这与此无关,因为这应该发生在配置步骤中,而不是在生成过程中,对吗
以下是我们观察到的情况:

  • 我们对不同的CMake版本进行了二进制搜索,得出的结论是,在3.15和3.16之间出现了巨大的减速,这正是添加了预编译头和unity build支持的时候,但我不认为这些特性与经济放缓有任何关系——我想不出它们产生如此影响的原因——一定是其他重构或更改
  • 我们禁用了所有测试(这意味着几乎所有600个可执行文件都被删除了)——将CMake目标的数量从700个减少到略多于100个——运行CMake所需的时间显著减少,但对于所有700个目标,仍然比使用CMake 2.6的时间长两倍
  • 我们使用
    strace
    观察了正在发生的事情,其中大部分是
    lstat
    access
    调用,以及一些读写操作——但这是无止境的——似乎每秒有数百个操作以非常可重复的方式进行。还有人不断尝试寻找
    libgflags。因此,
    总是失败。不幸的是,我现在没有这样的日志
  • 我们做了一个callgrind配置文件,下面是运行几分钟后的样子:(可以找到callgrind输出文件)-似乎大部分时间都花在
    ComputeLinkLibs()
    上,获取目标的全名和定义等等。。。有700个目标是不是太多了?这是一个指数问题吗?为什么CMake 3.15没有问题

我在网上找不到任何其他人有同样问题的报告。。。你知道下一步该怎么做吗?也许使用Perf配置文件?尝试将忍者作为后端()?

很棒的分析。这将有助于CMake的开发人员。但我怀疑你在这里能找到多少帮助。请打开一张支票


如果你能提供一个简单的例子来说明你的问题,那么你就可以获得额外的分数。您可能会通过生成大量文件来实现这一点。

是否应该将此情况报告给stackoverflow而不是stackoverflow?