释放速度:加速 Podman v5.6 中的并行层移除

容器镜像从根本上说是以一系列只读层的形式构建的,当创建容器实例时,通常会在顶部添加一个可写层。这种分层架构通过允许多个镜像共享公共基础层来促进高效存储和分发。然而,删除一个层,特别是可能被多个镜像或容器引用的层,是一个复杂的操作。

删除一个层不仅涉及删除物理数据,还涉及更新元数据、管理引用,并确保没有关键数据被无意中删除或处于不一致状态。在整个操作过程中,会持有一个锁,以防止其他进程访问存储。

存储锁不需要在层删除的整个过程中都被持有。层删除中最耗时的部分是从磁盘中删除物理数据。虽然固态硬盘加速了这一过程,但它们只部分解决了这个问题。频繁的层删除和其他 I/O 密集型操作会延长存储锁的持有时间,使存储对其他进程不可用。

如何更有效地删除文件?有什么操作比直接删除更快?一种方法是将文件移动到垃圾目录,允许它们在存储锁之外进行删除。然而,实现“垃圾”机制需要解决进程未能清空垃圾或多个进程需要访问其内容的情况。虽然移动文件可能是 I/O 密集型的,但将文件重命名到同一文件系统上的不同位置是一种有效的替代方案,尤其是在需要移动层中存在的大量文件时。

为了在位置之间移动文件,同时保留强大的锁定机制,防止其他线程访问同一目录,并实现强大的故障恢复,新的内部结构至关重要。为此,containers/storage 中通过此 提交 实现了一个具有恢复功能的内部临时目录。这个临时目录将来可以用于促进并行镜像拉取,防止相互阻塞。

为了有效地管理对临时目录的并行访问,每个 TempDir 实例在 NewTempDir() 初始化时立即获取并持有对其相应文件的独占锁。此锁作为指示,表明临时目录正被持有 TempDir 对象的进程或 goroutine 积极使用。反之,如果未持有锁,则临时目录被视为陈旧,并随后作为恢复过程的一部分进行清理。

临时目录的存在需要一个新的暂存锁。这是因为锁定存储中使用的文件会导致临时目录的旧锁文件在清理过程中泄漏。

通过在删除层时使用这种新的临时目录机制,现在可以实现优化的层删除。在层删除过程中,元数据会更新,引用会管理,并确保没有关键数据被无意中删除或处于不一致状态。文件不是被物理删除,而是被移动到临时目录。所有删除步骤完成后,这个临时目录会在存储锁之外进行清理。这大大减少了存储锁的持有时间。

为了验证这些优化的影响,进行了基准测试,比较了层删除优化实现前后层删除与并行列出镜像的情况。

基准测试

基准测试旨在通过模拟涉及两个并发操作的常见实际场景来量化优化层删除的性能提升。

  1. 后台容器镜像删除:优化的层删除机制将在后台启动容器镜像删除过程。此操作将获取存储锁,但由于延迟的物理文件删除,它会更快地释放锁。(此删除使用了 docker.io/tensorflow/tensorflow:latest-gpu 镜像。)
  2. 即时镜像列表:在启动删除后,将立即尝试镜像列表操作。此操作需要获取存储锁。镜像列表操作成功获取锁并完成所需的时间将是一个关键指标。

测量镜像列表操作完成所需的时间使我们能够直接评估层删除期间存储锁持有时间减少的影响。这表明 Podman v5.6 中其他存储操作的吞吐量和并发性得到了改进。
以下是执行基准测试的基本脚本的结果

之前

Untagged: docker.io/tensorflow/tensorflow:latest-gpu
Deleted: 94f506c52991baf5ead292f5a82dafe0480ef177d6a7846d671a206e9b0dd91b

real	0m1.787s
user	0m0.033s
sys	0m1.319s
REPOSITORY                           TAG             IMAGE ID      CREATED       SIZE
registry.fedoraproject.org/fedora    latest          2856f68043ad  5 weeks ago   176 MB
<none>                               <none>          feedd0289cd5  8 weeks ago   415 MB
<none>                               <none>          b56eb9950ba9  8 weeks ago   415 MB
<none>                               <none>          a30cf268d19a  2 months ago  176 MB
docker.io/library/eclipse-temurin    17-jdk-alpine   e3c32894dd61  2 months ago  334 MB
quay.io/libpod/testimage             20241011        13dc0b3d0b0a  9 months ago  14.2 MB
quay.io/libpod/alpine_nginx          latest          ecea49d99daa  3 years ago   23.1 MB
quay.io/libpod/alpine                latest          915beeae4675  5 years ago   5.59 MB

real	0m1.792s
user	0m0.050s
sys	0m1.364s

之后

REPOSITORY                         TAG            IMAGE ID      CREATED       SIZE
registry.fedoraproject.org/fedora  latest         2856f68043ad  5 weeks ago   176 MB
<none>                             <none>         feedd0289cd5  8 weeks ago   415 MB
<none>                             <none>         b56eb9950ba9  8 weeks ago   415 MB
<none>                             <none>         a30cf268d19a  2 months ago  176 MB
docker.io/library/eclipse-temurin  17-jdk-alpine  e3c32894dd61  2 months ago  334 MB
quay.io/libpod/testimage           20241011       13dc0b3d0b0a  9 months ago  14.2 MB
quay.io/libpod/alpine_nginx        latest         ecea49d99daa  3 years ago   23.1 MB
quay.io/libpod/alpine              latest         915beeae4675  5 years ago   5.59 MB

real	0m0.545s
user	0m0.007s
sys	0m0.057s
Untagged: docker.io/tensorflow/tensorflow:latest-gpu
Deleted: 94f506c52991baf5ead292f5a82dafe0480ef177d6a7846d671a206e9b0dd91b

real	0m1.492s
user	0m0.021s
sys	0m0.989s

通过这些 containers/storage 优化,镜像列表现在只需 0.545 秒,从 1.792 秒下降,在此实例中速度提高了 60%。即使在高性能机器(例如,带有快速 SSD 的 M3 Pro)上也可以测量到这种改进,因为镜像列表过程不再等待整个删除过程完成,并且排除了已删除的镜像。

这些结果清楚地表明存储锁的持有时间大幅减少,从而显着提高了 Podman v5.6 中层删除操作的吞吐量和并发性。将文件删除移出关键存储锁路径的能力将瓶颈转变为高效的后台进程,从而实现更流畅、更快的容器镜像管理。

发表评论

订阅

输入您的电子邮件地址以接收来自本网站的电子邮件更新。

返回

您的消息已发送

警告
警告
警告。

分类


搜索