Golang二进制文件差异分析工具v1.4:比较两个Go程序的变化内容

Golang二进制文件差异分析工具v1.4:比较两个Go程序的变化内容 GitHub - Zxilly/go-size-analyzer: 一个用于分析已编译Go二进制文件大小的工具

自 v1.4.0 版本起,go-size-analyzer 能够计算两个 Go 二进制文件之间的差异,精确到包和节(section),从而轻松找出导致二进制文件体积增大的原因。

$ gsa bin-linux-1.21-amd64 bin-linux-1.22-amd64
┌────────────────────────────────────────────────────────────────┐
│ Diff between bin-linux-1.21-amd64 and bin-linux-1.22-amd64     │
├─────────┬──────────────────────┬──────────┬──────────┬─────────┤
│ PERCENT │ NAME                 │ OLD SIZE │ NEW SIZE │ DIFF    │
├─────────┼──────────────────────┼──────────┼──────────┼─────────┤
│ +29.34% │ runtime              │ 782 kB   │ 1.0 MB   │ +229 kB │
│ add     │ internal/chacha8rand │          │ 3.1 kB   │ +3.1 kB │
│ +5.70%  │ <autogenerated>      │ 18 kB    │ 19 kB    │ +1.0 kB │
│ +8.70%  │ internal/abi         │ 6.0 kB   │ 6.6 kB   │ +525 B  │
│ +10.88% │ internal/cpu         │ 4.7 kB   │ 5.2 kB   │ +515 B  │
│ +4.45%  │ internal/reflectlite │ 3.9 kB   │ 4.1 kB   │ +173 B  │
│ +2.64%  │ internal/bytealg     │ 1.5 kB   │ 1.5 kB   │ +39 B   │
│ +0.81%  │ strconv              │ 4.0 kB   │ 4.0 kB   │ +32 B   │
│ +0.19%  │ syscall              │ 13 kB    │ 13 kB    │ +24 B   │
│ -0.17%  │ main                 │ 19 kB    │ 19 kB    │ -32 B   │
│ -0.37%  │ embed                │ 8.6 kB   │ 8.6 kB   │ -32 B   │
│ -0.38%  │ reflect              │ 25 kB    │ 25 kB    │ -96 B   │
│ -0.26%  │ time                 │ 87 kB    │ 86 kB    │ -224 B  │
│ -8.09%  │ sync                 │ 9.3 kB   │ 8.6 kB   │ -755 B  │
├─────────┼──────────────────────┼──────────┼──────────┼─────────┤
│ +7.59%  │ .rodata              │ 143 kB   │ 153 kB   │ +11 kB  │
│ +5.04%  │ .gopclntab           │ 144 kB   │ 152 kB   │ +7.3 kB │
│ +3.61%  │ .debug_info          │ 168 kB   │ 174 kB   │ +6.1 kB │
│ +3.52%  │ .debug_loc           │ 81 kB    │ 84 kB    │ +2.9 kB │
│ +3.03%  │ .debug_line          │ 80 kB    │ 82 kB    │ +2.4 kB │
│ +3.39%  │ .symtab              │ 59 kB    │ 61 kB    │ +2.0 kB │
│ +4.29%  │ .debug_frame         │ 29 kB    │ 30 kB    │ +1.2 kB │
│ +1.31%  │ .strtab              │ 61 kB    │ 62 kB    │ +795 B  │
│ +3.28%  │ .debug_ranges        │ 13 kB    │ 13 kB    │ +415 B  │
│ +5.13%  │ .data                │ 5.0 kB   │ 5.2 kB   │ +256 B  │
│ +7.32%  │ .typelink            │ 1.3 kB   │ 1.3 kB   │ +92 B   │
│ +27.78% │ .go.buildinfo        │ 288 B    │ 368 B    │ +80 B   │
│ -1.56%  │ .debug_gdb_scripts   │ 64 B     │ 63 B     │ -1 B    │
│ -0.63%  │ .noptrdata           │ 2.5 kB   │ 2.5 kB   │ -16 B   │
│ -6.48%  │ .shstrtab            │ 247 B    │ 231 B    │ -16 B   │
├─────────┼──────────────────────┼──────────┼──────────┼─────────┤
│ +3.86%  │ bin-linux-1.21-amd64 │ 1.6 MB   │ 1.6 MB   │ +61 kB  │
│         │ bin-linux-1.22-amd64 │          │          │         │
└─────────┴──────────────────────┴──────────┴──────────┴─────────┘

更多关于Golang二进制文件差异分析工具v1.4:比较两个Go程序的变化内容的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang二进制文件差异分析工具v1.4:比较两个Go程序的变化内容的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


go-size-analyzer v1.4.0 的差异分析功能确实为 Go 二进制文件的大小优化提供了强大的工具支持。它通过精确对比两个编译后的二进制文件,帮助开发者定位体积增长的具体来源。

以下是一个使用示例,展示了如何通过编程方式调用该工具进行差异分析:

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    // 定义要比较的两个二进制文件路径
    oldBinary := "bin-linux-1.21-amd64"
    newBinary := "bin-linux-1.22-amd64"
    
    // 构建 gsa 命令
    cmd := exec.Command("gsa", oldBinary, newBinary)
    
    // 设置输出
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    
    // 执行命令
    err := cmd.Run()
    if err != nil {
        fmt.Printf("执行差异分析失败: %v\n", err)
        os.Exit(1)
    }
}

该工具输出的差异报告分为三个主要部分:

  1. 包级别差异:显示各个 Go 包的大小变化,如 runtime 包增加了 229 kB
  2. 节区差异:显示 ELF 文件中各个节(section)的大小变化,如 .rodata 节增加了 11 kB
  3. 总体差异:显示整个二进制文件的总大小变化

对于需要集成到 CI/CD 流程中的场景,可以解析工具的 JSON 输出:

package main

import (
    "encoding/json"
    "fmt"
    "os/exec"
)

type DiffReport struct {
    Packages []PackageDiff `json:"packages"`
    Sections []SectionDiff `json:"sections"`
    Total    TotalDiff     `json:"total"`
}

type PackageDiff struct {
    Percent   string `json:"percent"`
    Name      string `json:"name"`
    OldSize   string `json:"old_size"`
    NewSize   string `json:"new_size"`
    Diff      string `json:"diff"`
}

type SectionDiff struct {
    Percent   string `json:"percent"`
    Name      string `json:"name"`
    OldSize   string `json:"old_size"`
    NewSize   string `json:"new_size"`
    Diff      string `json:"diff"`
}

type TotalDiff struct {
    Percent   string `json:"percent"`
    OldSize   string `json:"old_size"`
    NewSize   string `json:"new_size"`
    Diff      string `json:"diff"`
}

func analyzeBinaryDiff(oldBin, newBin string) (*DiffReport, error) {
    cmd := exec.Command("gsa", "--json", oldBin, newBin)
    output, err := cmd.Output()
    if err != nil {
        return nil, fmt.Errorf("执行 gsa 失败: %w", err)
    }
    
    var report DiffReport
    if err := json.Unmarshal(output, &report); err != nil {
        return nil, fmt.Errorf("解析 JSON 失败: %w", err)
    }
    
    return &report, nil
}

func main() {
    report, err := analyzeBinaryDiff("bin-linux-1.21-amd64", "bin-linux-1.22-amd64")
    if err != nil {
        fmt.Printf("分析失败: %v\n", err)
        return
    }
    
    // 检查特定包的变化
    for _, pkg := range report.Packages {
        if pkg.Name == "runtime" {
            fmt.Printf("runtime 包变化: %s (%s)\n", pkg.Diff, pkg.Percent)
        }
    }
    
    // 输出总体变化
    fmt.Printf("总体大小变化: %s (%s)\n", report.Total.Diff, report.Total.Percent)
}

这个工具特别适用于以下场景:

  • 比较不同 Go 版本编译的二进制文件
  • 分析依赖更新导致的大小变化
  • 评估优化措施的实际效果
  • CI 流程中监控二进制文件大小增长

通过精确的包级别和节区级别分析,开发者可以快速识别出导致二进制文件体积增大的具体组件,从而进行有针对性的优化。

回到顶部