这是我参与「第五届青训营 」笔记创作活动的第 4 天 。
一、本堂课重点内容
- Go 语言的性能优化建议,分析对比不同方式对性能的影响和背后的原理
- 常用性能分析工具 pprof 的使用和工作原理,熟悉排查程序性能问题的基本流程
二、详细知识点
1.错误和异常处理
1)错误的输出、判断和提取
- 自定义新错误:errors.New(string)
- 错误链关联:fmt.Errorf() ,与printf使用一致,错误用%w占位
- 错误判定,判断错误链上是否有指定错误:errors.Is(错误链, fs.指定错误)
- 错误提取:
var pathError *fs.PathError
errors.As(错误链,&pathError)
会将第二个参数类型的错误放在其中
2)异常处理
- panic(string) 终止程序并且抛出string
- recover()函数 recover()只能在defer里调用,且只对当前gorountine的被defer的函数中生效,会捕捉并返回当前函数的panic错误 如果需要上下文信息,可以在recover捕捉到错误后将当前调用栈关联到错误链中:
if e := recover(); e != nil {
err = fmt.Errorf("格式%s",debug.Stack())
}
2.性能优化
1)Benchmark基准测试
基准测试是对目标函数进行足够多次定量的测试。 在测试文件中要进行基准测试的函数要以 Benchmark 开头,并且在命令行输入命令时要加上参数 -bench=. -benchmem
func BenchmarkFib(b *testing.B){
for n := 0; n < b.N; n++ {
Fib(10)
}
}
2)Slice优化
- 预分配:尽可能在使用make()初始化切片时提供容量信息。
- 释放大内存:在较大原切片创建新的小切片,可以使用make后调用 copy(新切片,原切片要切的部分) 来避免新切片依然引用向大数组导致内存无法释放。
3)Map优化
- 预分配:尽可能在使用make()初始化切片时提供容量信息。
4)字符串处理
①字符串拼接
使用strings.Builder,避免大量的字符串直接相加。
var builder strings.Builder
builder.WriteString(str)
5)空结构体
当需要用到Set时,可以将使用map的key保存,而value设置为空结构体,将不占用任何空间
6)atomic包
对于单个数值变量在多线程中的安全,可以使用atomic包进行保护
type counter struct{
i int32
}
func AtomicAdd(c *counter,n int32){
atomic.AddInt32(&c.i,n)
}
- 效率会比锁高,锁一般用于保护逻辑
- 对于非数值操作,可以使用atomic.Value,能承载一个interface{}
3.性能分析工具pprof
- pprof是用于可视化和分析性能分析数据的工具 打开命令行后键入
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=10
其中second后的参数是要pprof测试多少秒
1)top命令
可以查看占用资源最多的函数,各参数意义如下:
Flat:函数中没有调用其他函数时,Flat==Cum;函数中只有其他函数的调用时,Flat==0
-
list 函数名 直接查看代码行占用资源
-
web 生成调用关系图
-
查看CPU占用情况
- go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/cpu"
-
排查堆内存问题
- go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
-
排查协程问题
- go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
-
排查锁问题
- go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
-
排查阻塞问题
-
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
-