Go性能调优 | 青训营笔记

60 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第 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命令

可以查看占用资源最多的函数,各参数意义如下: image.png Flat:函数中没有调用其他函数时,Flat==Cum;函数中只有其他函数的调用时,Flat==0