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

在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默认的环境变量,其实就是缓存位置:

dockerfile 复制代码
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中需要缓存的地方挂载出来:

toml 复制代码
[[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:

yaml 复制代码
---

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秒:

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

mold

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

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

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

toml 复制代码
[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秒。

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

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

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

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

dockerfile 复制代码
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配置为:

toml 复制代码
[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:

yaml 复制代码
builds:
  cpuLimit: 600m
  cpuRequests: 200m

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

yaml 复制代码
builds:
  cpuLimit: 1.5
  cpuRequests: 1

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

总结

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

相关推荐
longgggggggggggggggg1 小时前
curl -fsSL https://get.docker.com|sh 解释命令
docker
LuiChun1 小时前
docker django uwsgi 报错记录
docker·容器·django
tingting01191 小时前
docker 释放磁盘空间--常用清理命令
运维·docker·容器
杨浦老苏1 小时前
轻量级安全云存储方案Hoodik
docker·群晖·网盘
SomeB1oody1 小时前
【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用
开发语言·后端·rust
dessler2 小时前
Docker-Dockerfile案例(一)
linux·运维·docker
香吧香2 小时前
已有docker镜像构建过程分析
docker
SomeB1oody3 小时前
【Rust自学】6.3. 控制流运算符-match
开发语言·前端·rust
undeflined3 小时前
vite + vue3 + tailwind 启动之后报错
开发语言·后端·rust