mcpField
G
go-performance

go-performance

github.com/cxuu开发1861.3k 次安装19 周前更新
代码仓库

关于 go-performance

面向优化 Go 热路径的开发者,介绍关注内存分配的编码方式、字符串处理和基准测试,并强调先测量再保留优化。

主要功能

  1. 01使用 strconv 转换基本类型
  2. 02避免重复进行字符串到字节转换
  3. 03为映射和切片指定容量
  4. 04字符串拼接策略
  5. 05基准测试与性能分析指引

适用场景

  1. 01减少热路径中的内存分配
  2. 02优化字符串转换与构建
  3. 03通过基准测试衡量性能变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cxuu/golang-skills --skill go-performance

安装后在 Claude Code 中输入/go-performance确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
BENCHMARKS.md
STRING-OPTIMIZATION.md
scripts/
bench-compare.sh

详细介绍

Go 性能模式

资源路由

  • scripts/bench-compare.sh - 比较基准测试结果、保存基线或生成 JSON 基准测试元数据时运行。
  • references/BENCHMARKS.md - 编写基准测试、使用 benchstat 或通过 pprof 进行性能分析时阅读。
  • references/STRING-OPTIMIZATION.md - 优化字符串转换、拼接或字节与字符串边界时阅读。

仅对热路径应用性能相关指南。不要过早优化——重点关注这些模式最重要的地方。


优先使用 strconv,而非 fmt

在将基本类型转换为字符串或从字符串转换时,strconv 比 fmt 更快:

s := strconv.Itoa(rand.Int()) // ~2x faster than fmt.Sprint()
方法速度分配次数
fmt.Sprint143 ns/op2 allocs/op
strconv.Itoa64.2 ns/op1 allocs/op

避免重复进行字符串到字节的转换

在循环外将固定字符串转换为 []byte 一次:

data := []byte("Hello world")
for b.Loop() { // Go 1.24+; use b.N loops only for older Go
    w.Write(data) // ~7x faster than []byte("...") each iteration
}

尽可能指定容器容量

尽可能指定容器容量,以便预先分配内存。这样可以最大限度地减少添加元素时因复制和调整大小而产生的后续分配。

Map 容量提示

使用 make() 初始化 map 时提供容量提示:

m := make(map[string]os.DirEntry, len(files))

注意:与切片不同,map 容量提示不保证完全预分配——它只是估算所需的 hashmap 桶数量。

切片容量

使用 make() 初始化切片时提供容量提示,尤其是在执行追加操作时:

data := make([]int, 0, size)

与 map 不同,切片容量不是提示——编译器会精确分配相应大小的内存。在达到容量之前,后续的 append() 操作不会产生任何分配。

方法时间(1 亿次迭代)
不指定容量2.48s
指定容量0.21s

容量版本由于追加时无需重新分配,速度约快 12 倍。


按值传递

不要仅仅为了节省几个字节而将指针作为函数参数传递。如果函数始终只通过 *x 引用参数 x,那么该参数就不应该是指针。

func process(s string) { // not *string — strings are small fixed-size headers
    fmt.Println(s)
}

常见的按值传递类型:string、io.Reader、小型结构体。

例外情况:

  • 复制开销较大的大型结构体
  • 未来可能会扩大的小型结构体

字符串拼接

根据复杂程度选择合适的策略:

方法最适用场景
+少量字符串,简单拼接
fmt.Sprintf混合类型的格式化输出
strings.Builder循环或逐步构建
strings.Join拼接切片
反引号字面量多行固定文本

基准测试与性能分析

优化前后务必进行测量。使用 Go 内置的基准测试框架和性能分析工具。

go test -bench=. -benchmem -count=10 ./...

验证:应用优化后,运行 bash scripts/bench-compare.sh,测量实际效果。只保留能带来可测量改进的优化。


快速参考

模式不佳做法推荐做法改进效果
整数转字符串fmt.Sprint(n)strconv.Itoa(n)速度约快 2 倍
重复转换为 []byte在循环中使用 []byte("str")在循环外转换一次速度约快 7 倍
Map 初始化make(map[K]V)make(map[K]V, size)更少的分配
切片初始化make([]T, 0)make([]T, 0, cap)速度约快 12 倍
小型固定大小参数*string、*io.Readerstring、io.Reader无间接访问
简单字符串拼接s1 + " " + s2(本来就不错)少量字符串使用 +
循环构建字符串重复使用 +=strings.BuilderO(n),而非 O(n²)

相关技能

  • 数据结构:选择切片、映射和数组,或了解分配语义时,请参阅 go-data-structures
  • 声明模式:使用带容量提示的 make,或初始化映射和切片时,请参阅 go-declarations
  • 并发:在多个 goroutine 之间并行处理工作,或使用 sync.Pool 重用缓冲区时,请参阅 go-concurrency
  • 风格原则:判断某项优化是否值得牺牲可读性时,请参阅 go-style-core

评论

支持 Markdown