type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
goroutine
本质
由go运行时管理
初始栈空间2KB
调度成本低,上线下文切换比OS线程快10-100倍
GMP模型
内存模型
内存布局
栈内存:协程的独立栈、自动管理无需手动释放
堆内存:动态分配、垃圾回收、指针引用
全局数据区:存储全局变量;程序启动时分配生命周期与程序相同。
内存分配TCMalloc
分级分配
mcache
mcentral
mheap
内存逃逸:内存从栈到堆
go build -gcflags="-m" main.go
场景
闭包函数、大块内存、指针逃逸、变量大小不确定
垃圾回收
三色标记:根对象开始扫描、递归扫描引用;清除阶段;并发执行
GC关键参数
堆内存增长2倍触发GC
强制触发GC
监控GC:runtime.ReadMemStats获取HeapAlloc
性能优化
减少堆分配:利用逃逸分析优化
控制内存增长:避免大对象频繁的分配释放;设置合理的GOGC
手动管理,不建议尝试
encoding/json
延迟解析:json.RawMessage
反射
常见性能问题诊断
CPU占用高:CPU Profile—使用top查看热点函数—list查看具体代码
内存占用高:heap profile—使用top查看内存分配—使用list看分配电
goroutine泄漏:采集协程profile—分析协程数量;检查协程创建点—确定报协程有退出机制
锁竞争:采集mutex profile—使用top查看锁等待时间-优化锁粒度或者使用无锁结构
性能调优工具
pprof
分析类型
CPU分析
内存分析
阻塞的分析
goroutine分析
查看命令
top:最消耗资源的函数
list函数名:查看函数具体的代码和耗时
web:生成调用图
peek:看函数及其他调用者的信息
traces:查看所有采样站
trace
关键指标
协程的生命周期
调度延迟
网络/系统调用阻塞
锁竞争
gc活动
分析视图
时间线可视化
协程分析
网络阻塞分析
同步阻塞分析
系统调用阻塞分析
调度延迟分析
常见问题
CPU使用率高:无限循环、复杂代码、频繁序列化和反序列化
内存问题:协程泄漏、全局变量积累、未关闭资源
协程泄漏:通道channel阻塞、无限循环、waitGroup使用不当、未处理的context取消:func leak(ctx context.Context) {
go func() {
select { // 只监听一个channel,没有处理ctx.Done()
case <-time.After(time.Minute):
fmt.Println("done")
}
}()
}
并发的问题:死锁
GC压力:频繁GC、GC停顿时间长
GC时间长
原因
堆内存过大
对象图复杂
高频率分配内存
设置了不合理的GC参数
优化方案
减少内存分配,使用协程池;避免在热度路径上分配内存
优化数据结构:使用值类而非指针类;减少不必要的指针分配;
调整GC参数
优化架构:大对象拆分为小对象;减少全局对象
网络和IO瓶颈:连接池太少
并发模型
GMP:runtime包查询GMP数据
channel高级模式
工作池
func workerPool(workers int, tasks <-chan Task) {
var wg sync.WaitGroup
wg.Add(workers)
for i := 0; i < workers; i++ {
go func(id int) {
defer wg.Done()
for task := range tasks {
process(task)
}
}(i)
}
wg.Wait()
}