为什么Go语言编写的二进制文件在Windows平台首次打开较慢

2026-11-07 20:04:00
丁国栋
原创 10
摘要:本文记录和整理在Windows平台中使用go语言编写二进制的一些现象或问题。

在使用go编写的二进制时,我注意到首次执行为什么比较慢,第二次就快了?例如我打了一个--help,大约需要几秒钟,而再次打开就一下子就打开了。


第一次:接近6秒

PS C:\Users\dgden\repo\dfgo> Measure-Command { .\bin\dfgo.exe --help }                        
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 848
Ticks             : 58483293
TotalDays         : 6.76889965277778E-05
TotalHours        : 0.00162453591666667
TotalMinutes      : 0.097472155
TotalSeconds      : 5.8483293
TotalMilliseconds : 5848.3293
PS C:\Users\dgden\repo\dfgo>
第二次:只有0.061秒

PS C:\Users\dgden\repo\dfgo> Measure-Command { .\bin\dfgo.exe --help }
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 61
Ticks             : 610371
TotalDays         : 7.06447916666667E-07
TotalHours        : 1.695475E-05
TotalMinutes      : 0.001017285
TotalSeconds      : 0.0610371
TotalMilliseconds : 61.0371
PS C:\Users\dgden\repo\dfgo> 

而且这个很容易复现,只要重新编译一下go二进制,就可以复现这个现象。


根据AI的回答,说这是个纯操作系统/环境层面的现象,和 Go 语言本身关系不大。--help 第二次"秒开"说明程序逻辑本身极快,第一次的几秒消耗在进程启动前的加载与检查上。按可能性排序:

1. Windows Defender / 杀毒软件实时扫描(最常见的一种原因)

第一次执行时,Windows Defender 的"实时保护"会对这个新出现的、未知的可执行文件做完整扫描(解包、特征匹配、云端信誉查询),扫完并建立信任缓存后,第二次就直接放行。自己编译的、没有签名、没有信誉累积的二进制尤其明显。

2. 磁盘冷读 vs 页缓存(Page Cache)

第一次执行时,二进制文件内容要从磁盘(尤其机械硬盘、NAS、或经过 Sync 同步盘的目录)真正读入内存;第二次时文件已经在 Windows 的 standby 内存缓存里,无需 IO。

3. SmartScreen / 签名检查

无 Authenticode 签名的 exe,Windows 可能做信誉检查,有时还会发起网络请求(CRL 吊销列表查询),网络慢时会卡一两秒。

4. Go 运行时自身开销(占比很小)

Go 二进制是静态编译,无 JIT 预热;runtime 初始化(GC、goroutine 调度器、TLS 根证书加载等)通常只有几十毫秒,不是主因。注意:很多"Java/Node 第一次慢"是 JIT/解释器预热,Go 不存在这个问题。

如何验证是哪一个原因

在 PowerShell 里实测:

# 连续测两次,看差距
Measure-Command { .\dfgo.exe --help }
# 查二进制大小(越大,冷读和扫描越慢)
(Get-Item .\dfgo.exe).Length / 1MB 

进一步定位:

  • 把项目目录加入 Defender 排除项(设置 → 病毒和威胁防护 → 排除项),再删掉 exe 重新编译执行,如果第一次也变快了 → 就是 AV 扫描。
  • 如果 exe 有几十 MB(vendor 依赖、embed 资源多),可以换 SSD 或先 type dfgo.exe > nul 预热缓存再执行,验证是不是 IO 冷读。

缓解手段

  • 开发期:把构建输出目录(如 ./bin)加进 Defender 排除项,收益立竿见影。
  • 发布期:给二进制做 Authenticode 代码签名,积累 SmartScreen 信誉。
  • 编译时去掉调试信息缩小体积:go build -ldflags "-s -w",配合 UPX 压缩(注意 UPX 反而可能加重 AV 扫描,需实测权衡)。

还没有评论,来做第一个吧!

称呼
邮箱
博客分类