为什么go build占用了大量内存

1,201 阅读2分钟

背景

昨天在线上发布微服务一直处于失败状态,后来运维同事观察到是由于go build指令几乎占满了服务器8G内存,于是指令直接被服务器kill掉了。

企业微信截图_16728285974989.png

然后我在自己的mac上用同一份代码执行go build,观察到在第一次编译的时候也使用了将近7G的内存。但无论后面编译多少次,go build的执行速度都非常快,且几乎不占什么内存。

分析过程

首先我得知道go build指令在做些什么事情,于是想到能不能从go help build获取什么有用的信息。将指令帮助信息浏览了一遍发现了如下信息: image.png

go build -n这条命令似乎能帮助我们分析go build做了些什么。下图截取了部分go build -n输出的内容,可以看出来go build是在将微服务所有依赖生成二进制文件,放在了红框的目录下。这就是go build的再次执行的编译速度会快很多的原因:依赖的二进制文件都已经缓存到了某个目录下,不需要再次编译依赖。 image.png

去到红框的目录下会发现还有个README文件,里面写着清理这些二进制文件的指令go clean -cacheimage.png

执行完go clean -cache后,再次执行go build会发现编译再次占用大量内存。

解决思路

暂时有以下两种解决思路:

  1. 保留缓存的依赖二进制文件;
  2. 删除微服务中不合理的依赖路径。

我们目前采取的是第二种方式,因为发布方式是使用docker image构建微服务,当前运维部门暂时没有缓存上一次打包的依赖二进制文件,所以当前只能从微服务本身的代码(删除微服务中不合理的依赖路径)来解决问题。