Golang项目编译速度过慢的优化方案探讨
Golang项目编译速度过慢的优化方案探讨
最近,我的 go build 变得非常慢。
下面的跟踪信息表明,虽然编译本身(exec.Builder.Do)相当快,只用了7秒,
但加载模块(load.PackagesAndErrors)却异常缓慢,耗时31秒!
大部分时间都花在了:
- modfetch.download
- modload.loadImport
这些函数在做什么?我们如何消除它们或加快它们的速度?
更多关于Golang项目编译速度过慢的优化方案探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个有趣的发现!差异有多大?
如果可能的话,我也会尝试另一台机器,以排除特定于机器的问题。
更多关于Golang项目编译速度过慢的优化方案探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我正在运行 go version 命令。
go version go1.20.4 windows/amd64
在我的另一台运行 Go 1.19 的笔记本电脑上,速度几乎相同。
你当前使用的是哪个版本?我注意到,与我当前的版本相比,构建速度明显比 1.19 慢。以下是我的版本信息:
go version go1.20.4 windows/amd64
如果你也在使用 1.20,可以尝试降级到 1.19。我原以为是我本地安装出了问题,但如果你也遇到了同样的情况,那这可能与 1.20 版本有关?不太确定。
你好 Christoph,
抱歉,链接似乎是仅限本地的。 我已将跟踪文件上传至:
https://temp-file.org/yXZFItP2p6demoX/file
你可以在 https://ui.perfetto.dev/ 上打开它。
不仔细看的话,可能是你的构建过程下载了大量模块,或者大型模块,可能还是通过慢速连接进行的。
我可以在没有网络的情况下构建我的程序,所以连接问题可以排除。 我知道我笔记本电脑的磁盘速度相当慢,这可能是个问题。 但是,我想知道如何能证实这一点?我推测加载模块确实需要大量的磁盘查找操作?
很难确切地说,因为我之前没有做过任何基准测试,但感觉确实慢了不少。我的开发机器性能相当不错,并且在某些项目中,我使用 cortesi/modd 来监视并持续构建我的 API(类似于使用 preact watch 这样的工具,但用于我的后端),因此我对构建时间的减慢特别敏感。如果通过 vendoring 我的依赖项能解决这个问题,那会很有趣(因为 @fumin 指出大部分时间都花在了 modfetch.download 上)。
对我来说,这只是个小麻烦,正如我提到的,我原本以为是我环境中的某些问题,所以没有花太多时间去排查。而且,如果这是 1.20 版本中的一个退步,几乎可以肯定会在某个时候被发现并修复。
从构建跟踪来看,编译速度慢的主要瓶颈在于模块依赖的下载和加载阶段。modfetch.download 负责下载依赖模块,modload.loadImport 负责解析和加载这些依赖。以下是具体的优化方案:
1. 启用模块缓存持久化
Go 1.15+ 支持模块缓存持久化,可减少重复下载:
# 设置环境变量
export GOMODCACHE=$HOME/.go/modcache
export GOPROXY=direct
export GOSUMDB=off # 仅测试环境使用,生产环境需谨慎
2. 使用 GOPROXY 加速
配置可靠的代理服务器:
# 使用阿里云代理
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
# 或使用官方代理
go env -w GOPROXY=https://proxy.golang.org,direct
3. 预下载依赖
在 CI/CD 或开发环境中预下载所有依赖:
# 下载所有依赖到本地缓存
go mod download
# 并行下载(Go 1.17+)
go mod download -x
4. 优化 go.mod 结构
检查并清理未使用的依赖:
# 整理 go.mod 文件
go mod tidy
# 验证依赖图
go mod verify
5. 使用 vendor 目录
将依赖固化到项目中:
# 创建 vendor 目录
go mod vendor
# 编译时使用 vendor
go build -mod=vendor
6. 升级 Go 版本
Go 1.16+ 改进了模块加载机制:
# 检查当前版本
go version
# 升级到最新稳定版(如 1.21+)
7. 分析依赖树
使用工具识别深层依赖:
# 查看依赖图
go mod graph | head -20
# 使用 go-mod-graph 可视化
示例:完整优化脚本
#!/bin/bash
# 设置优化环境
export GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
export GOMODCACHE=$HOME/.go/cache
export GO111MODULE=on
# 清理并重新下载
go clean -modcache
go mod download
# 使用并行编译
go build -p 8 -v ./...
关键指标验证
优化后可通过以下命令验证:
# 测量构建时间
time go build -v ./...
# 查看模块缓存大小
du -sh $(go env GOMODCACHE)
这些方案能显著减少 modfetch.download 和 modload.loadImport 的执行时间。实际效果取决于网络环境和项目依赖复杂度。


