Go性能优化示例
概述
本文档展示了Go语言的性能优化技巧,包括内存优化、并发优化、算法优化、性能分析等。
运行示例
bash
cd apps/go/examples/05-performance
go run main.go
核心概念
1. 性能分析
go
import (
"runtime/pprof"
"os"
)
func startCPUProfile() {
f, err := os.Create("cpu.prof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
func startMemoryProfile() {
f, err := os.Create("mem.prof")
if err != nil {
log.Fatal(err)
}
defer f.Close()
pprof.WriteHeapProfile(f)
}
2. 内存优化
go
// 对象池
import "sync"
var bufferPool = sync.Pool{
New: func() interface{} {
return make([]byte, 1024)
},
}
func getBuffer() []byte {
return bufferPool.Get().([]byte)
}
func putBuffer(buf []byte) {
bufferPool.Put(buf)
}
3. 并发优化
go
// 工作池
func workerPool(jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// 启动工作协程
for w := 1; w <= 3; w++ {
go workerPool(jobs, results)
}
// 发送任务
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
// 收集结果
for a := 1; a <= 9; a++ {
<-results
}
}
4. 算法优化
go
// 字符串拼接优化
func inefficientConcat() string {
var result string
for i := 0; i < 1000; i++ {
result += "a"
}
return result
}
func efficientConcat() string {
var builder strings.Builder
for i := 0; i < 1000; i++ {
builder.WriteString("a")
}
return builder.String()
}
5. 缓存优化
go
import (
"sync"
"time"
)
type Cache struct {
data map[string]interface{}
mu sync.RWMutex
}
func (c *Cache) Get(key string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
value, exists := c.data[key]
return value, exists
}
func (c *Cache) Set(key string, value interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
示例代码
详细示例请查看 main.go
文件,包含:
- 性能分析工具使用
- 内存优化技巧
- 并发性能优化
- 算法性能优化
- 缓存策略
- 数据库优化
- 网络优化
- 编译优化
性能优化工具
- pprof: Go内置的性能分析工具
- go tool trace: 追踪分析工具
- benchmark: 基准测试
- go build: 编译优化
- go vet: 代码检查
- golangci-lint: 代码质量检查
优化技巧
1. 内存优化
- 使用对象池减少GC压力
- 避免不必要的内存分配
- 使用sync.Pool复用对象
- 合理使用切片容量
2. 并发优化
- 使用goroutine池
- 避免goroutine泄漏
- 合理使用channel缓冲
- 使用sync包进行同步
3. 算法优化
- 选择合适的数据结构
- 优化循环和条件判断
- 使用字符串构建器
- 避免频繁的字符串拼接
4. 编译优化
bash
# 编译优化
go build -ldflags="-s -w" main.go
# 交叉编译
GOOS=linux GOARCH=amd64 go build main.go
性能监控
go
import (
"runtime"
"time"
)
func printMemStats() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
fmt.Printf("\tNumGC = %v\n", m.NumGC)
}
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
学习要点
- 分析: 使用性能分析工具找出瓶颈
- 优化: 针对瓶颈进行优化
- 测试: 使用基准测试验证优化效果
- 监控: 持续监控应用性能
- 平衡: 在性能和可读性之间找到平衡
下一步
- 学习部署运维 (06-deployment)