在容器中编译时性能损失较大

在容器中编译时性能损失较大

概括

在构建大型 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} )

,但从警告的角度来看,这是不可取的,例如

我的问题是:

  • 为什么容器化构建速度那么慢?
  • 我还能做些什么来避免这种情况

相关内容