提高GitLab CICD效率:Rust编译速度飙升秘籍

2023年 7月 25日 57.4k 0

在GitLab CICD的流水线作业中,发现Rust编译速度是个瓶颈,因为耗费CPU,非常缓慢,一次构建居然需要20几分钟,这大大超出我们的心理预期。

sccache

经过调研,发现sccache可以优化二次编译的速度。本质上是将编译结果以某种方式缓存,下次编译时可以复用。

它可以使用cargo install sccache直接安装,也可以使用二进制文件,在这里下载sccache-v0.3.0-x86_64-unknown-linux-musl.tar.gz。也可以用代理加速:archive.fastgit.org/mozilla/scc…。

对于我们而言,我们可以将sccache的编译结果存储在NAS中,这样不同的工作空间就可以共享缓存。

优化

修改GitLab Runner运行时镜像,Rust默认的环境变量,其实就是缓存位置:

FROM rust:1.62.1

WORKDIR /app

ENV TZ "Asia/Shanghai"
# 更改cargo的默认位置,在物理机上通常是~/.cargo,而容器里是/usr/local/cargo
ENV CARGO_HOME="/rust-cache/cargo"
# 更改rustc的编译文件
ENV RUSTC_WRAPPER="/rust-cache/bin/sccache"
# 更改sccache的默认缓存位置,也就是~/.cache/sccache
ENV SCCACHE_DIR="/rust-cache/sccache"

再在K8S使用helm创建GitLab Runner用到的图——gitlab-runner中需要缓存的地方挂载出来:

[[runners.kubernetes.volumes.pvc]]
name = "runner-rust-cache"
mount_path = "/rust-cache/config" 
sub_path = "config"
readOnly = true

[[runners.kubernetes.volumes.pvc]]
name = "runner-rust-cache"
mount_path = "/rust-cache/sccache"   
sub_path = "sccache"
readOnly = true

[[runners.kubernetes.volumes.pvc]]
name = "runner-rust-cache"
mount_path = "/rust-cache/bin/sccache"
sub_path = "bin/sccache"

[[runners.kubernetes.volumes.pvc]]
name = "runner-rust-cache"
mount_path = "/rust-cache/registry/cache" 
sub_path = "registry/cache" 

[[runners.kubernetes.volumes.pvc]]
name = "runner-rust-cache"
mount_path = "/rust-cache/registry/index"   
sub_path = "registry/index" 

这里的runner-rust-cache,是需要挂载的pvc:

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: runner-rust-cache
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  storageClassName: runner-rust-cache
  mountOptions:
    - vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport
  nfs:
    server: "xx.amazonaws.com.cn"
    path: "/mnt/runner/rust"

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: runner-rust-cache
  namespace: gitlab-runner
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: runner-rust-cache
  resources:
    requests:
      storage: 10Gi

验证

挂载前,24分36秒:
image.png

挂载后7分14秒:
image.png
这个时间虽然仍不理想,但差强人意。

mold

mold是现有Unix链接器的更快的替代品。它比LLVM lld链接器快几倍,后者是第二快的开源链接器。mold旨在通过最小化构建时间,特别是在快速调试-编辑-重建周期中,提高开发人员的生产力。

所以重点是,它可以加快链接速度,也就是我们使用cargo build看到控制台一系列输出编译中的最后一步(前面都是编译具体某个包,最后一步是将这些内容整合)。在这里下载:github.com/rui314/mold…,或者换用代理加速:archive.fastgit.org/rui314/mold…。

需要在cargo目录的config中配置:

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/xx/mold-1.4.0-x86_64-linux/bin/mold"]

第一次耗时正常是23分14秒。

image.png

加了mold之后是20分30秒,节省了不到3分钟。

image.png

有了sccache缓存后,正常是7分54秒:

image.png

加了mold以后是6分18秒,节省了一分半。

image.png

以下是一个集成了sccache和mold的基础镜像,用来在流水线中构建产物(运行cargo build):

FROM rust:alpine3.17

WORKDIR /app

RUN set -eux && sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories 
  && apk update 
  && apk add --no-cache musl-dev pkgconfig openssl-dev clang wget make git bzip2 ca-certificates python3 bash build-base coreutils gcompat libgcc libc-dev

RUN mkdir download && cd download 
  && wget https://github.com/rui314/mold/releases/download/v1.4.0/mold-1.4.0-x86_64-linux.tar.gz && tar xzvf mold-1.4.0-x86_64-linux.tar.gz && mv mold-1.4.0-x86_64-linux ../mold 
  && wget https://github.com/mozilla/sccache/releases/download/v0.3.0/sccache-v0.3.0-x86_64-unknown-linux-musl.tar.gz && tar xzvf sccache-v0.3.0-x86_64-unknown-linux-musl.tar.gz && mv sccache-v0.3.0-x86_64-unknown-linux-musl/sccache ../ && chmod +x /app/sccache  
  && apk del -f wget 
  && rm -rf /var/lib/apt/lists/* && rm -rf ../download 

ENV TZ "Asia/Shanghai"
ENV CARGO_HOME="/rust-cache/cargo"
ENV RUSTC_WRAPPER="/app/sccache"
ENV SCCACHE_DIR="/rust-cache/sccache"
ENV RUSTFLAGS="-C target-feature=-crt-static"

CMD /bin/bash

这里安装了不少依赖,都是我们项目中用到的,读者可以视情况做些删减。

我们线上的cargo配置为:

[source.crates-io]
replace-with = 'tuna'

[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/app/mold/bin/mold"]

调整CPU

我们本机构建Rust产物也没有那么慢,为什么流水线就那么慢呢?

相对于前端项目,Rust的构建可谓是非常消耗CPU了。我们的前端项目构建通常在3分钟左右,最长的有10分钟。

所以针对Rust项目,调大runner的CPU,原来是200m:

builds:
  cpuLimit: 600m
  cpuRequests: 200m

修改为1,相当于从0.2升到1:

builds:
  cpuLimit: 1.5
  cpuRequests: 1

第一次缩减到5分钟,使用sccache后缩减到3分钟左右,这样差不多就可以忍受了。
image.png

总结

在GitLab CICD的流水线作业中,Rust编译速度是个瓶颈,我们通过sccache共享缓存和使用mold加速链接,以及最终调整runner分配的CPU,将一个项目首次耗时从23分钟降到5分钟,后续耗时降到3分钟左右,极大地提高了我们的生产效率。

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论