learning_notes

学习笔记

View project on GitHub

优化

go 优化

  1. 注重锁的使用,尽量做到锁变量而不要锁过程 ,可以使用CAS机制,则使用CAS操作
  2. 针对热点代码要做针对性优化
  3. 不要忽略 GC 的影响,尤其是高性能低延迟的服务,使用对象池,声明切片定义容量
  4. 尽量避免反射,在高性能服务中杜绝反射的使用
  5. 有些情况下可以尝试调优“GOGC”参数
  6. 新版本稳定的前提下,尽量升级新的 Go 版本
  7. 对频繁分配的小对象,使用 sync.Pool 对象池避免分配
  8. 自动化的 DeepCopy 是非常耗时的,其中涉及到反射,内存分配,容器(如 map)扩展等,大概比手动拷贝慢一个数量级
  9. 在开发环境开启 net/http/pprof,方便实时 pprof
  10. 将所有外部IO(网络IO,磁盘IO)做成异步

参数化分析

  • -gcflags=-m :查看编译器的逃逸分析和内联决定
  • GODEBUG=gctrace=1 :开启gc跟踪

具体优化

  1. string与byte的转化,会在底层发生内存拷贝,直接修改指针
func Str2bytes(s string) []byte {
	x := (*[2]uintptr)(unsafe.Pointer(&s))
	h := [3]uintptr{x[0],x[1],x[1]}
	return*(*[]byte)(unsafe.Pointer(&h))
}

func Bytes2str(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

  1. map 会按需扩张,但须付出数据拷贝和重新哈希成本。如有可能,应尽可能预设足够容量空间,避免此类行为发生
m := make(map[string]int,10)
  1. 对于小对象,直接将数据交由 map 保存,远比用指针高效。这不但减少了堆内存分配,关键还在于垃圾回收器不会扫描非指针类型 key/value 对象
m := make(map[string]int,10) //值数据
m := make(map[string]*int,10) //指针数据
  1. 对于map类型,delete不会减少内存占用,只有将map至为nil才会释放内存

  2. defer尽量少写或者合并,defer会注册延迟调用函数,影响性能

  3. 闭包会导致变量逃逸到堆上,造成GC负担,同时闭包会增加开销

  4. 对于压力很大的内部组件之间,用接口有些得不偿失,普通调用用内联