概括
在构建大型 C/C++ 代码库时,Docker 容器中的构建时间比操作系统中的构建时间长 3.5 倍。可以通过将 Conan 包管理器提供的所有第三方包含声明为非系统包含来缓解此问题。问题是是否可以通过其他方式缩短容器化构建时间。
设置
构建服务器:
- AMD EPYC 7742 双 CPU,带 512GB 内存
- SMT 已关闭
- Debian sid,内核 5.18.5-1
- Docker CE,20.10.14+dfsg1(服务器)
- SELinux:关闭;Apparmor:关闭;缓解措施:关闭
构建容器:
- CentOS 7
- GCC 9.3.1(devtoolset-9)
- CMake 3.18
- 柯南 1.44.1
- 忍者 1.10.0
容器选项:
- 特权: true (也用 false 测试过)
- SecurityOpt:“seccomp=unconfined”、“label=disabled”
- 内存大小:4G
- 没有资源限制(所有 CPU、所有内存)
描述
我一直在调查在 Docker 容器中编译基于 C/C++ 的软件时构建速度大幅下降的问题。
为了建立基准,我直接在操作系统中编译了软件。对于一个约 4.5k 个源文件的子项目,构建耗时 170 秒 +/- 0.14%(三次运行的平均值)。使用了所有 128 个内核。当我在构建容器中编译同一个子项目时,需要 531 秒 +/- 0.25% 才能完成。由于所有额外时间都花在了系统中,因此我perf top -g
使用一个 CPU 进行整个构建。这是我得到的结果:
Children Self Shared Object Symbol
+ 81.89% 0.02% [kernel] [k] entry_SYSCALL_64_after_hwframe
+ 81.81% 0.02% [kernel] [k] do_syscall_64
+ 69.87% 0.02% [kernel] [k] vfs_fstatat
+ 63.56% 0.06% [kernel] [k] vfs_statx
+ 60.76% 0.01% [kernel] [k] __do_sys_newlstat
+ 57.43% 57.37% [kernel] [k] avc_lookup
+ 54.22% 0.05% [kernel] [k] filename_lookup
+ 54.06% 0.03% [kernel] [k] path_lookupat
+ 50.17% 0.49% [kernel] [k] link_path_walk.part.0.constprop.0
+ 43.15% 0.15% [kernel] [k] inode_permission
+ 42.31% 0.05% [kernel] [k] ovl_permission
+ 35.90% 0.04% [kernel] [k] override_creds
+ 19.00% 0.00% [unknown] [k] 0x00007f02abb49505
+ 18.99% 0.00% [unknown] [k] 0x00007f2f95987505
+ 13.59% 2.38% [kernel] [k] revert_creds
+ 12.46% 10.66% [kernel] [k] selinux_inode_permission
+ 7.63% 0.02% [kernel] [k] complete_walk
+ 7.62% 0.26% [kernel] [k] lockref_get_not_dead
+ 7.59% 0.02% [kernel] [k] try_to_unlazy
+ 7.51% 0.04% [kernel] [k] __legitimize_path
+ 6.73% 0.00% cc1plus [.] 0x00000000015f44b6
+ 6.56% 0.01% [kernel] [k] do_sys_openat2
+ 6.23% 0.01% [kernel] [k] do_filp_open
+ 5.49% 0.00% libc-2.17.so [.] 0x00007f2e3a46b505
+ 5.37% 0.01% [kernel] [k] path_openat
+ 5.34% 0.00% [kernel] [k] __x64_sys_open
+ 5.05% 0.05% [kernel] [k] getname_flags.part.0
+ 4.88% 0.01% [kernel] [k] ovl_getattr
该项目使用 Conan 进行依赖管理,并使用 CMake 配置构建工具 Ninja。Conan 软件包提供的所有包含文件均声明为系统包含文件:
include_directories( SYSTEM ${CONAN_INCLUDE_DIRS} )
当我运行构建时,构建容器中的构建时间大约比在外部构建时慢 3.5 倍。额外的时间完全花在内核中的函数avc_code
和上selinux_inode_permision
。
我发现的解决方法是将 Conan 包中的所有包含内容配置为“非”系统包含内容:
set( CMAKE_NO_SYSTEM_FROM_IMPORTED ON )
include_directories( ${CONAN_INCLUDE_DIRS} )
,但从警告的角度来看,这是不可取的,例如
我的问题是:
- 为什么容器化构建速度那么慢?
- 我还能做些什么来避免这种情况