我有一个 SCons 脚本,它需要大约 10 秒才能发现不需要重建任何东西,这对于本质上是一个相当小的项目来说感觉非常长。阅读 SConscript 本身只需要一两秒钟,大部分时间花在:
scons: Building targets ...
步。
我怎样才能知道此时到底scons
在做什么?对于编写快速 SCons 脚本,还有哪些其他一般性建议?
我有一个 SCons 脚本,它需要大约 10 秒才能发现不需要重建任何东西,这对于本质上是一个相当小的项目来说感觉非常长。阅读 SConscript 本身只需要一两秒钟,大部分时间花在:
scons: Building targets ...
步。
我怎样才能知道此时到底scons
在做什么?对于编写快速 SCons 脚本,还有哪些其他一般性建议?
(直接盗用http://www.scons.org/wiki/GoFastButton)
命令 'scons --max-drift=1 --implicit-deps-unchanged' 将尽可能快地执行您的构建。
或者:
使事情变得更快的另一个技巧是避免在共享库已修改但未重建时重新链接程序。请参阅SharedLibrarySignatureOverride
scons md5-sums 文件以找出它们已更改,因此它几乎 md5sums 您的所有文件。
您可以告诉它只使用时间戳来决定要重建什么,而不必每次都对所有文件进行 MD5sum ,就像'make'所做的那样,这应该会加快速度。它可能更脆弱。例如,如果文件在上次构建后的 1 秒内发生了变化,scons 不会注意到这一点。采用
env.Decider('timestamp-newer')
还有 MD5-timestamp,它会先检查时间戳,如果时间戳较新,则使用 Md5 比较内容是否实际更改。
env.Decider('MD5-timestamp')
另一个加快速度的简单选择是使用 -j 参数运行并行构建。
scons -j 2
在我的 2 核机器上,-j 3 通常会提供最大的加速。
可以使用调用 scons 的 --debug 参数来完成关于 scons 正在做什么的一些输出,请参阅手册页以了解各种选项。
做了一些试验和错误来弄清楚为什么 SCons 很慢,到目前为止的一些发现(确切的结果当然会根据 SCons 脚本的结构和复杂性而有所不同):
CacheDir()
没有明显的负面影响。Decider()
只有很小的影响,不值得打扰。variant_dir
/VariantDir()
将构建时间增加约 10%。SConstruct
文件本身大约需要完成 scons 调用的 10%。可能的解决方案:
scons -u
而不是scons -D
)。SConscript
可选的部分,因此它仅在手动调用时重建。-isystem
使用库包含的编译器标志而不是-I
,仅此更改就将构建时间从 10.5 秒缩短到 6 秒,只需调用 sed 即可轻松完成:
env.ParseConfig('pkg-config --cflags --libs gtkmm-2.4 | sed "s/-I/-isystem/g"')
不完全确定为什么会这样,我假设它减少了gcc
输出的依赖关系,从而减少了scons
跟踪的依赖关系。
当然也强烈推荐使用CacheDir()
and scons -j N
,但只会加速实际构建,而不是对 SCons 脚本本身的评估。
将第 3 方包括移出 CPPPATH 并移入 CCFLAGS 产生了巨大的变化。对于我们有 12 个外部包含目录(包括 boost 和 python)的项目,无操作编译从 30 秒缩短到 3 秒——加速了 10 倍。
当 SCons 首次创建时Environment
,它会进行一系列查找以查看可用的工具。您可以通过DefaultEnvironment
在创建第一个env
.
DefaultEnvironment(tools=[])
添加到您的 SConscript 类似
if 'explain' in GetOption("debug"):
Progress('Evaluating $TARGET\n')
并运行--debug=explain
. 您将看到 SCons 花费时间评估的内容
scons --profile
+snakeviz
这种组合向我展示了瓶颈到底是什么。
--profile
cProfile
以格式输出二进制文件,该文件存在于 stdlib 中。
snakeviz
然后是一个很棒的可视化工具,可以在 GUI 中快速查看该文件:
scons --profile f.prof
pip install -u snakeviz
snakeviz f.prof
输出如下所示:
您可以将鼠标悬停在每个框上以查看包含该函数的文件的完整路径。
更一般的 Python 上下文中的问题:是否有任何简单的方法来对 python 脚本进行基准测试?
--debug
+ts -s
这并没有解决我的具体问题,但它通常可以给你一些想法:
--debug
标志,或所有看起来有趣的标志ts -s
,它显示每行何时出现在标准输出上:如何监控标准输出的每一行是 Bash 中用于基准测试的最后一个输出行的时间?time scons --debug=count,duplicate,explain,findlibs,includes,memoizer,memory,objects,prepare,presub,stacktrace,time |
ts -s | tee f
示例输出摘录显示了我在 2 到 10 秒之间的巨大时间间隔,这是我试图集中注意力的地方:
00:00:02 SConscript:/data/gem5/master3/build/ARM/sim/power/SConscript took 1.556 ms
00:00:02 dup: relinking variant 'build/ARM/sim/probe/SConscript' from 'src/sim/probe/SConscript'
00:00:02 Building build/ARM/sim/probe/SConscript with action:
00:00:02 UnlinkFunc(target, source, env)
00:00:02 Building build/ARM/sim/probe/SConscript with action:
00:00:02 LinkFunc(target, source, env)
00:00:02 SConscript:/data/gem5/master3/build/ARM/sim/probe/SConscript took 0.401 ms
00:00:10 SConscript:/data/gem5/master3/build/ARM/tests/opt/SConscript took 98.225 ms
00:00:10 SConscript:/data/gem5/master3/build/ARM/SConscript took 8885.387 ms
00:00:10 SConscript:/data/gem5/master3/SConstruct took 9409.641 ms
00:00:10 scons: done reading SConscript files.
00:00:10 scons: Building targets ...
在 scons 3.0.1、Ubuntu 18.04 中测试。
也可以看看