# Golang 性能优化 ## 问题 1. Go 的性能分析工具有哪些? 2. pprof 如何使用? 3. 如何减少内存分配? 4. 如何优化 CPU 性能? 5. 如何进行并发性能优化? 6. Go 的性能优化最佳实践是什么? --- ## 标准答案 ### 1. 性能分析工具 #### **pprof(CPU 和内存分析)** ```bash # CPU 性能分析 go test -cpuprofile=cpu.prof -bench . # 内存分析 go test -memprofile=mem.prof -bench . # 可视化 go tool pprof -http=:8080 cpu.prof ``` --- #### **trace** ```go import ( "os" "runtime/trace" ) func main() { f, _ := os.Create("trace.out") defer f.Close() trace.Start(f) defer trace.Stop() // 程序逻辑 } ``` --- ### 2. pprof 使用 #### **CPU 分析** ```bash # 生成 CPU profile go test -cpuprofile=cpu.prof -bench=. # 查看 go tool pprof cpu.prof # 列出 top 函数 go tool pprof -top cpu.prof # 可视化 go tool pprof -http=:8080 cpu.prof ``` --- #### **内存分析** ```bash # 生成 heap profile go test -memprofile=heap.prof -bench=. # 查看 go tool pprof heap.prof # 查看内存分配 go tool pprof -alloc_space heap.prof ``` --- ### 3. 减少内存分配 #### **1. 使用 sync.Pool** ```go var bufPool = sync.Pool{ New: func() interface{} { return make([]byte, 1024) }, } func process(data []byte) { buf := bufPool.Get().([]byte) defer bufPool.Put(buf) copy(buf, data) // ... } ``` --- #### **2. 预分配容量** ```go // ❌ 多次扩容 var s []int for i := 0; i < 1000; i++ { s = append(s, i) } // ✅ 预分配 s := make([]int, 0, 1000) for i := 0; i < 1000; i++ { s = append(s, i) } ``` --- ### 4. CPU 性能优化 #### **1. 减少系统调用** ```go // ❌ 多次系统调用 var b bytes.Buffer for i := 0; i < 1000; i++ { b.WriteString(strconv.Itoa(i)) } // ✅ 批量写入 var b bytes.Buffer for i := 0; i < 1000; i++ { b.WriteString(strconv.Itoa(i)) } ``` --- #### **2. 避免不必要的拷贝** ```go // ❌ 拷贝 func process(data []byte) { copy := make([]byte, len(data)) copy(copy, data) // ... } // ✅ 使用切片 func process(data []byte) { sub := data[10:20] // ... } ``` --- ### 5. 并发性能优化 #### **1. 使用 Worker Pool** ```go func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { results <- j * j } } func main() { jobs := make(chan int, 100) results := make(chan int, 100) // 启动 4 个 worker for i := 0; i < 4; i++ { go worker(i, jobs, results) } // 发送任务 for i := 0; i < 100; i++ { jobs <- i } close(jobs) // 收集结果 for i := 0; i < 100; i++ { <-results } } ``` --- #### **2. 减少 Lock 竞争** ```go // ❌ 全局锁 var mu sync.Mutex func process(id int) { mu.Lock() defer mu.Unlock() // ... } // ✅ 分片锁 var mu [16]sync.Mutex func process(id int) { idx := id % 16 mu[idx].Lock() defer mu[idx].Unlock() // ... } ``` --- ### 6. 性能优化最佳实践 #### **1. 使用 pprof 分析瓶颈** ```bash # CPU 分析 go tool pprof -http=:8080 cpu.prof # 内存分析 go tool pprof -http=:8080 heap.prof # 火焰图 go tool pprof -http=:8080 -http=:8080 -pdf cpu.prof > cpu.pdf ``` --- #### **2. 优化热点代码** ```go // 使用 pprof 找到热点函数 // go tool pprof -list functionName cpu.prof // 优化前 func slow() { for i := 0; i < 1000000; i++ { s := fmt.Sprintf("%d", i) // 慢 _ = s } } // 优化后 func fast() { var b strings.Builder for i := 0; i < 1000000; i++ { b.WriteString(strconv.Itoa(i)) } _ = b.String() } ``` --- ### 7. 阿里 P7 加分项 **深度理解**: - 理解 pprof 的数据采集原理 - 理解 Go 的性能瓶颈(内存、CPU、Goroutine) - 理解 Go 的 GC 对性能的影响 **实战经验**: - 有使用 pprof 优化程序性能的经验 - 有优化并发程序的经验(减少锁、使用 Worker Pool) - 有优化内存使用的经验(sync.Pool、预分配) **性能优化**: - 理解如何进行性能分析和瓶颈定位 - 理解如何优化 CPU 密集型代码 - 理解如何优化 I/O 密集型代码