Jam*_*noa 8 c++ linker precompiled-headers build-time
我的 externalFiles 目录中有 100 个 .h 文件。我的源代码中大约有 10 个 .cpp 文件包含这些 .h 文件。
因此,我#include externalFiles/.*h从 .cpp 文件中删除了所有指令,并将它们写入通过 Cmake 包含的 pch.h 标头中target_precompile_headers(${PROJECT_NAME} PRIVATE pch.h)。
我通过 Cmake 使用预编译头检查了构建时间,而不是简单地将 pch.h 包含在我的 .cpp 文件中。我使用以下方法记录了构建时间:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")和
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CMAKE_COMMAND} -E time")
使用预编译头构建时间
[1/2] 构建 CXX 对象 CMakeFiles/AlgoCoding.dir/main.cpp.obj
经过时间:11 秒。(时间),11.413 秒。(钟)
[2/2] 链接 CXX 可执行文件 AlgoCoding.exe
经过时间:54 秒。(时间),53.459 秒。(钟)
构建时间仅包括标头
[1/2] 构建 CXX 对象 CMakeFiles/AlgoCoding.dir/main.cpp.obj
经过时间:14秒。(时间),13.35 秒。(钟)
[2/2] 链接 CXX 可执行文件 AlgoCoding.exe
经过时间:28 秒。(时间),28.109 秒。(钟)
结论
从这些时间来看,使用预编译头似乎确实减少了修改后的 .cpp 文件(main.cpp)的 .obj 创建的构建时间,但它大大增加了链接时间。
每个人都是这样还是我在这里做错了什么?
编辑:1
实验 #2测试预编译头的构建时间。
我尝试将 spdlog 库(包含 100 个 .h 文件的仅标头库)包含到我的基本 Cmake 项目中(只是一个 main.cpp 将 1 行记录到文件中)。有两种方法可以做到这一点。
target_precompile_headers(${PROJECT_NAME} PRIVATE pch.h))构建时间结果
----方法一
[1/2] 构建 CXX 对象 CMakeFiles/test.dir/main.cpp.obj
经过时间:22 秒。(时间),21.904 秒。(钟)
[2/2] 链接 CXX 可执行文件 test.exe
经过时间:18秒。(时间),18.311 秒。(钟)
----方法二
[1/2] 构建 CXX 对象 CMakeFiles/test.dir/main.cpp.obj
经过时间:18秒。(时间),18.231 秒。(钟)
[2/2] 链接 CXX 可执行文件 test.exe
经过时间:22 秒。(时间),21.604 秒。(钟)
结论
在准系统项目中预编译外部头文件仍然提供与仅使用 #include 指令相同的总构建时间。使用预编译标头时,构建 .obj 文件所需时间的小幅减少将通过链接 CXX 可执行文件所需时间的增加来补偿。
在预编译外部 .h 文件时,我需要做一些不同的事情来减少构建时间吗?或者这是预期的行为?
正如 @HolyBlackCat 所建议的,我尝试使用clang + LLD linker进行相同的编译。对于普通的 #include 头文件和预编译头(约 100 个 .h 文件)来说,构建时间确实得到了改善:
-------方法1(普通#include)
[1/2] 构建CXX对象 CMakeFiles/test.dir/main.cpp.obj
花费时间:7秒。(时间),6.997 秒。(时钟)
[2/2] 链接 CXX 可执行文件 test.exe
所用时间:9 秒。(时间),9.493 秒。(钟)
-------方法2(预编译头)
[1/2] 构建CXX对象 CMakeFiles/test.dir/main.cpp.obj
花费时间:5秒。(时间),4.515 秒。(时钟)
[2/2] 链接 CXX 可执行文件 test.exe
所用时间:9 秒。(时间),9.076 秒。(钟)
从这些结果来看,Clang+LLD 的执行速度明显快于 gcc+LD/gold。此外,与 Clang+LLD 一起使用时,预编译头能够减少总体构建时间,因为它减少了 .obj 文件的构建时间,但能够实现类似的链接时间。(请参阅问题编辑 1,了解 gcc+默认链接器的构建时间)
此外,@Marco van de Voort 提到要检查使用预编译头缩放 .obj/.cpp 文件的数量如何影响构建时间。因此,对于方法 2(预编译头文件),我使用 3 个 .cpp 文件(Scaling 3)和 5 个 .cpp 文件(Scaling 5)进行编译。结果如下:
-----方法 2 缩放 3 .cpp
构建所有 3 个 CXX
所用时间:7 秒。(时间),6.767 秒。(时钟)
[4/4] 链接 CXX 可执行文件 test.exe
所用时间:27 秒。(时间),27.404 秒。(钟)
-----方法 2 缩放 5 .cpp
构建所有 5 个 CXX 对象
所用时间:11 秒。(时间),11.416 秒。(时钟)
[6/6] 链接 CXX 可执行文件 test.exe
所用时间:47 秒。(时间),46.942 秒。(钟)
我们可以看到链接的时间增加是线性的〜(9 *要链接到的#cpp文件)。对于方法 1,缩放会产生更差的结果。
尽管与 Clang+LLD 一起使用时预编译头文件可以提供更好的构建时间,但最好使用方法 3。找到您尝试使用的仅头文件库的库版本 (.lib/.dll) 。该库是静态/动态链接的,这样构建时间要快得多。
方法3:在Cmake中使用spdlog库(通过vcpkg安装):
set(CMAKE_PREFIX_PATH "<PathToVcpkg>\\installed\\x64-mingw-static") # THIS HAS TO COME BEFORE THE PROJECT LINE
project(test)
find_package(spdlog REQUIRED);
add_executable(${PROJECT_NAME} ${project-targets})
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog::spdlog )
Run Code Online (Sandbox Code Playgroud)
与使用仅标头库(包含 PCH)相比,使用 .lib 库版本(包含 PCH)的构建时间显着缩短:
-----方法 3 缩放 1 .cpp
[1/2] 构建 CXX 对象 CMakeFiles/test.dir/main.cpp.obj
花费时间:2 s。(时间),2.073 秒。(时钟)[2/2] 链接 CXX 可执行文件 test.exe
所用时间:10 秒。(时间),10.294 秒。(钟)
-----方法 3 缩放 5 .cpp
[5/6] 构建 CXX 对象 CMakeFiles/test.dir/main2.cpp.obj
花费时间:2 s。(时间),2.244 秒。(时钟)[6/6] 链接 CXX 可执行文件 test.exe
所用时间:12 秒。(时间),12.024 秒。(钟)