golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Contex ...

火影  金牌会员 | 2023-7-19 16:39:06 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 551|帖子 551|积分 1653

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
使用 benchmark 压测过程中通常会出现这样的信息:
  1. go test -v -bench=. -benchmem
  2. f1     10000        120860 ns/op        2433 B/op         28 allocs/op
  3. f2     10000        120288 ns/op        2288 B/op         26 allocs/op
复制代码
可以看见  f1 在每次运行都产生了  28 次内存分配。
gc 通常是  golang  最大的性能杀手,减少内存分配对性能提升非常明显。
可以把程序区分为 hot path 和 非hot path,hot path 即运行最频繁,消耗时间最多的程序执行路径。VictoriaMetrics 的作者  Valyala 建议在  Hot path 上做到  0 alloc.
然而,必须需要在函数间传递的对象指针,必然需要引起 alloc。减少内存分配的一个办法是  sync.Pool,但是如果在 A 函数中使用 sync.Pool.Get, 而在 B  函数中使用  sync.Pool.Put,这样的程序流程比较混乱,不容易维护。且,当存在大量的不同对象时,其 sync.Pool 的种类也很多;sync.Pool 还有全局锁,会影响程序的并发性。
VictoriaMetrics 中大量的使用了这样的技巧:
1. 定义自己的 Context 对象
  1. type MyContext struct{
  2. }
  3. // 业务函数的第一个参数都是 MyContext
  4. func BizFunc1(ctx *MyContext){}
  5. func BizFunc2(ctx *MyContext){}
复制代码
2. 所有在函数间传递的变量(引起栈逃逸的),都定义在 MyContext 中
  1. type MyContext struct{
  2.      tempBuffer []byte
  3. }
  4. //  如果函数都依赖 tempBuffer, 把局部变量定义到 MyContext 中
  5. func BizFunc1(ctx *MyContext){
  6.      ctx.tempBuffer = append(ctx.tempBuffer, "str1"...)
  7. }
  8. func BizFunc2(ctx *MyContext){
  9.     ctx.tempBuffer = append(ctx.tempBuffer, "str2"...)
  10. }
复制代码
3. MyContext 本身从  sync.Pool 中获取
  1. var poolOfMyContext = sync.Pool{
  2.     New: func() interface{}{
  3.         return &MyContext{}
  4.     }
  5. }
  6. // 业务入口函数
  7. func BizEntrance(){
  8.     ctx := poolOfMyContext.Get().(*MyContext)
  9.     defer poolOfMyContext.Put(ctx)
  10.     //
  11.     callBizFunc(ctx)  // 业务逻辑函数
  12. }
复制代码
4. MyContext 对象提供 Reset() 方法

对分配好的各种缓冲区重用,避免反复分配。
  1. func (c *MyContext) Reset() {
  2.      c.tempBuffer = c.tempBuffer[:0]  // 重用分配好的空间
  3. }
  4. // 业务入口函数
  5. func BizEntrance(){
  6.     ctx := poolOfMyContext.Get().(*MyContext)
  7.     ctx.Reset()  // 需要清空内容,避免上次的数据干扰运行结果
  8.     defer poolOfMyContext.Put(ctx)
  9.     //
  10.     callBizFunc(ctx)  // 业务逻辑函数
  11. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表