golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Context 对象中来做到hot path 的 0 alloc

这篇具有很好参考价值的文章主要介绍了golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Context 对象中来做到hot path 的 0 alloc。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!

  • cnblogs博客
  • zhihu
  • Github
  • 公众号:一本正经的瞎扯
    golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Context 对象中来做到hot path 的 0 alloc

使用 benchmark 压测过程中通常会出现这样的信息:

go test -v -bench=. -benchmem
f1     10000        120860 ns/op        2433 B/op         28 allocs/op
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 对象

type MyContext struct{

}

// 业务函数的第一个参数都是 MyContext
func BizFunc1(ctx *MyContext){}

func BizFunc2(ctx *MyContext){}

2. 所有在函数间传递的变量(引起栈逃逸的),都定义在 MyContext 中

type MyContext struct{
     tempBuffer []byte
}

//  如果函数都依赖 tempBuffer, 把局部变量定义到 MyContext 中
func BizFunc1(ctx *MyContext){
     ctx.tempBuffer = append(ctx.tempBuffer, "str1"...)
}

func BizFunc2(ctx *MyContext){
    ctx.tempBuffer = append(ctx.tempBuffer, "str2"...)
}

3. MyContext 本身从 sync.Pool 中获取

var poolOfMyContext = sync.Pool{
    New: func() interface{}{
        return &MyContext{}
    }
}

// 业务入口函数
func BizEntrance(){
    ctx := poolOfMyContext.Get().(*MyContext)
    defer poolOfMyContext.Put(ctx)
    //
    callBizFunc(ctx)  // 业务逻辑函数
}

4. MyContext 对象提供 Reset() 方法

对分配好的各种缓冲区重用,避免反复分配。文章来源地址https://www.toymoban.com/news/detail-582418.html

func (c *MyContext) Reset() {
     c.tempBuffer = c.tempBuffer[:0]  // 重用分配好的空间
}

// 业务入口函数
func BizEntrance(){
    ctx := poolOfMyContext.Get().(*MyContext)
    ctx.Reset()  // 需要清空内容,避免上次的数据干扰运行结果
    defer poolOfMyContext.Put(ctx)
    //
    callBizFunc(ctx)  // 业务逻辑函数
}

到了这里,关于golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Context 对象中来做到hot path 的 0 alloc的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言趣味教程】(6) 作用域:局部变量 | 全局变量 | 局部变量优先原则 | 利用大括号限制作用域 | 变量的生命周期

        🔗 【C语言趣味教程】专栏介绍👈 猛戳了解!!! 0x00 引入:什么是作用域? 变量和常量在程序中都是有作用范围的,这个范围我们称之为变量的  作用域 (scope) 。 作用域也称为 \\\"定义域\\\",是程序中 定义的变量所存在的区域,出了该区域变量就不能被访问。 变量的作

    2024年02月14日
    浏览(52)
  • 【C语言趣味教学】(6) 作用域:局部变量 | 全局变量 | 局部变量优先原则 | 利用大括号限制作用域 | 变量的生命周期

        🔗 【C语言趣味教程】专栏介绍👈 猛戳了解!!! 0x00 引入:什么是作用域? 变量和常量在程序中都是有作用范围的,这个范围我们称之为变量的  作用域 (scope) 。 作用域也称为 \\\"定义域\\\",是程序中 定义的变量所存在的区域,出了该区域变量就不能被访问。 变量的作

    2024年02月14日
    浏览(33)
  • 涨知识-关于局部内部类访问局部变量

    局部内部类访问局部变量必须用final修饰 局部内部类在访问它所在方法中的局部变量必须用final修饰,为什么? 因为当调用这个方法时,局部变量如果没有final修饰,它的生命周期和方法的生命周期是一样的, 当方法弹栈时,这个局部变量也会消失。 那么如果局部内部类对象

    2024年02月03日
    浏览(45)
  • Java成员变量(全局变量)和局部变量

    在Java中变量类型有 成员变量 、 局部变量 和 静态变量(类变量、static变量) ,本篇文章主要介绍成员变量(全局变量)和局部变量的区别。 根据变量的作用范围,将程序中的变量分为成员变量(全局变量)和局部变量。 一、成员变量(全局变量) 成员变量(全局变量):

    2024年02月04日
    浏览(42)
  • Python的全局变量、局部变量、类变量、实例变量介绍

    Python 的变量分类 全局变量:模块内、所有函数外、所有class外的变量; 局部变量:函数内的变量,class的方法内且不使用self.修饰的变量; 类变量:class内且不在class的方法内; 实例变量:class的方法内且使用self.修饰的变量。 对于面向过程程序设计涉及: 全局变量:模块中

    2024年02月03日
    浏览(54)
  • 通过模仿学会Python爬虫(一):零基础上手

    好家伙,爬虫来了   爬虫,这玩意,不会怎么办, 诶,先抄一份作业回来  Python爬虫史上超详细讲解(零基础入门,老年人都看的懂)_ChenBinBini的博客-CSDN博客    卧槽,有点东西 这东西看上去挺nb啊, 也很方便,把我想要的一些数据直接总结到一个excel表格中了     我们

    2024年02月09日
    浏览(58)
  • c语言全局变量和局部变量问题汇总

    ✅作者简介:嵌入式领域优质创作者,博客专家 ✨个人主页:咸鱼弟 🔥系列专栏:单片机设计专栏  1、static的作用是什么?  定义静态变量  2、static有什么用途?(请至少说明两种)  1).限制变量的作用域(在程序的整个运行期间都不释放)  2).设置变量的存储域(存

    2024年02月06日
    浏览(42)
  • Java 成员变量与局部变量有什么区别?

    节选自JavaGuide(Github 标星 134k star!「Java学习 + 面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识) 语法形式 :从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被 public , private , static 等修饰符所修

    2024年02月05日
    浏览(50)
  • MySQL数据库——存储过程-变量(系统变量、用户定义变量、局部变量)

    目录 系统变量  1.查看系统变量  2.设置系统变量 演示示例 用户定义变量 1.赋值  2.使用 演示示例 局部变量 声明  赋值 演示示例 变量 在MySQL中变量分为三种类型: 系统变量、用户定义变量、局部变量。 系统变量是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全

    2024年02月05日
    浏览(53)
  • 堆,栈,程序区,静态变量,局部变量,函数,参数宏

           堆和栈是堆和栈是在程序运行中用于 存储数据和指令 的两种不同的内存空间。 堆:堆内存是 用于分配程序中动态数据结构的内存空间 ,它的生命周期不由 程序的函数调用栈管理 ,通常会被 程序员 直接管理。        堆空间为程序 提供了极为灵活的空间分配和管

    2024年01月24日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包