C++服务编译耗时优化原理及实践( 三 )


C++服务编译耗时优化原理及实践

文章插图
 
每个服务所面临的编译问题都有各自的特点,但是遇到问题的本质原因是类似的,结合编译的过程和原理,我们从预编译展开、头文件依赖以及编译过程耗时3个方面对DQU服务编译问题进行了分析 。
3.1 编译展开分析
编译展开分析就是通过C++的预编译阶段保留的.ii文件,查看通过展开后的编译文件大小,具体可以通过在cmake中指定编译选型 “-save-temps” 保留编译中间文件 。
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS} -ggdb -Og -fPIC -w -Wl,--export-dynamic -Wno-deprecated -fpermissive -save-temps")编译耗时的最直接原因就是编译文件展开之后比较大,通过编译展开后的文件大小和内容,通过预编译展开分析能看到文件展开后的文件有40多万行,发现有大量的Boost库引用及头文件引用造成的展开文件比较大,影响到编译的耗时 。通过这个方式能够找到各个文件编译耗时的共性,下图是编译展开后文件大小截图 。
C++服务编译耗时优化原理及实践

文章插图
 
3.2 头文件依赖分析
头文件依赖分析是从引用头文件数量的角度来看代码是否合理的一种分析方式,我们实现了一个脚本,用来统计头文件的依赖关系,并且分析输出头文件依赖引用计数,用来辅助判断头文件依赖关系是否合理 。
1. 头文件引用总数结果统计
通过工具统计出编译源文件直接和间接依赖的头文件的总个数,用来从头文件引入数量上分析问题 。
C++服务编译耗时优化原理及实践

文章插图
 
2. 单个头文件依赖关系统计
通过工具分析头文件依赖关系,生成依赖关系拓扑图,能够直观的看到依赖不合理的地方 。
图中包含引用层次关系,以及引用头文件个数 。
C++服务编译耗时优化原理及实践

文章插图
 
3.3 编译耗时结果分段统计
编译耗时分段统计是从结果上看各个文件的编译耗时以及各个编译阶段的耗时情况,这个是直观的一个结果,正常情况下,是和文件展开大小以及头文件引用个数是正相关的,cmake通过指定环境变量能打印出编译和链接阶段的耗时情况,通过这个数据能直观的分析出耗时情况 。
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CMAKE_COMMAND} -E time")编译耗时结果输出:
C++服务编译耗时优化原理及实践

文章插图
 
3.4 分析工具建设
通过上面的工具分析能拿到几个编译数据:
① 头文件依赖关系及个数 。
② 预编译展开大小及内容 。
③ 各个文件编译耗时 。
④ 整体链接耗时 。
⑤ 可以计算出编译并行度 。
通过这几个数据的输入我们考虑可以做个自动化分析工具,找出优化点以及界面化展示 。基于这个目的,我们建设了全流程自动化分析工具,能够自动分析耗时共性问题以及TopN耗时文件 。分析工具处理流程如下图所示:
C++服务编译耗时优化原理及实践

文章插图
 
1. 整体统计分析效果
C++服务编译耗时优化原理及实践

文章插图
 
具体字段说明:
① cost_time 编译耗时,单位是秒 。
② file_compile_size,编译中间文件大小,单位是M 。
③ file_name,文件名称 。
④ include_h_nums,引入头文件个数,单位是个 。
⑤ top_h_files_info,引入最多的TopN头文件 。
2. Top10 编译耗时文件统计
用来展示统计编译耗时最久的TopN文件,N可以自定义指定 。
C++服务编译耗时优化原理及实践

文章插图
 
3. Top10编译中间文件大小统计
通过统计和展示编译文件大小,用来判断这块是否符合预期,这个是和编译耗时一一对应的 。
C++服务编译耗时优化原理及实践

文章插图
 
4. Top10引入最多头文件的头文件统计
C++服务编译耗时优化原理及实践

文章插图
 
5. Top10头文件重复次数统计
C++服务编译耗时优化原理及实践


推荐阅读