golang: 模仿 VictoriaMetrics 中的做法,通过把局部变量放在自定义 Context 对象中来做到hot path 的 0 alloc
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
使用 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() 方法
对分配好的各种缓冲区重用,避免反复分配。
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的更多相关文章
- .NET中利用反射来实现自动映射两个对象中的数据成员
在以前的项目开发之中,经常会遇到这样一个问题:比如在外面项目的架构设计之中,我们采用MVC和EntityFramework来构建一个Web应用程序.比如我们采用常用的多层架构,例如有Presentat ...
- CSS中2d转换:transition过渡放在:hover伪类中与应用在整个元素中区别
css的2d转换十分强大,能够在不使用js的情况下,实现页面的元素与用户之间更多动态的交互,增强用户体验.其中使用最多的就是hover伪类. 1.创建一个页面的div元素: <!DOCTYPE ...
- JavaScript中的内置对象-8--4.date对象中-获取,设置日期时间的方法; 获取,设置年月日时分秒及星期的方法;
学习目标 1.掌握创建日期对象的方法 2.掌握date对象中获取日期时间的方法 3.掌握date对象中设置日期时间的方法 如何创建一个日期对象 语法:new Date(); 功能:创建一个日期时间对象 ...
- Flexigrid从对象中加载数据
(有问题,在找…………) Flexigrid是用来动态加载数据的一种比较好(老)的Jquery表插件,然后有些时候,我们需要其从本地或者jQuery对象中加载数据,比如有这么个需求,页面显示中有两个表 ...
- JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法
1.原型属性对象于in操作符之in单独使用 有两种方式使用in操作符:单独使用和在for-in循环中使用.在单独使用中,代码如下: function Person(){ } Person.protot ...
- c++ , const对象中的变量不能被修改
const对象中的变量不能被修改,即使const对象中的函数也不能修改该对象中的变量值 #include <iostream> using namespace std; //------- ...
- 设计模式系列之迭代器模式(Iterator Pattern)——遍历聚合对象中的元素
模式概述 模式定义 模式结构图 模式伪代码 模式改进 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修 ...
- 使用 history 对象和 location 对象中的属性和方法制作一个简易的网页浏览工具
查看本章节 查看作业目录 需求说明: 使用 history 对象和 location 对象中的属性和方法制作一个简易的网页浏览工具 实现思路: 使用history对象中的 forward() 方法和 ...
- ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中
如果解决ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中 手机平台性能是个关键问题. 压缩视频分成3个步骤: 读取显卡数据, 使用编码器压缩,保存文件. 使用libav 压缩的 ...
- js中如何以最简单的方式将数组元素添加到对象中
//如题,通常做法就是循环数组,最后在添加length属性,如: var obj = {}; var pushArr = [11,22,33,44,55,66]; for(var i=0;i<p ...
随机推荐
- 面对 Log4j2 漏洞,安全人都做了什么?
摘要:本文从漏洞复现.漏洞防护.漏洞检测.软件供应链安全等方面,介绍安全人针对该漏洞做的尝试. 本文分享自华为云社区<面对 Log4j2 漏洞,安全人都做了什么?>,作者:maijun. ...
- 非root安装Anaconda
1.下载对应版本的Anaconda (wget+路径) 下载地址:https://repo.anaconda.com/archive/ 或者清华镜像:https://mirrors.tuna.tsin ...
- Solon2 之 Kotlin 语言开发后端项目,很爽
今天也学别人用 Solon 框架写个 Kotlin 后端项目.自己搞配置还是有点难的,需要借助 "Solon Initializr" 生成个项目模板. 1.生成项目模板 打开&qu ...
- PPT 图片8大操作技巧
如何实现图片的批量导入 插入相册 图片批量导出 7z 直接解压 修改扩展名 -> 解压 PPT 抠图 设备透明色 删除背景色 二次曝光效果 低版本 office 通过,形状来实现 图片融入背景 ...
- cmd 7z 文件压缩
7z压缩测试 为了方便,将7z的安装目录,添加到环境变量中 # 不加环境变量的话,需要带上全路径 C:\Users\vipsoft>"C:\\Program Files\\7-Zip\ ...
- Jmeter对各种接口类型的测试
JMeter对各种类型接口的测试 默认做接口测试前,已经给出明确的接口文档(如,http://test.nnzhp.cn/wiki/index.php?doc-view-59):本地配好了JMeter ...
- 非洲 AI 不发达,看看这份PPT,受益匪浅
非洲 AI 不发达,看看这份PPT,受益匪浅 非洲有大量的工程+机器学习人才,他们渴望学习.努力工作和进步. 大家好,我是老章 看到我关注的一位博主在首届非洲 @LangChainAI 聚会上的一个演 ...
- Mysql--JOIN连表查询
一.Join查询原理 MySQL内部采用了一种叫做 nested loop join(嵌套循环连接)的算法:通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表 ...
- 洛谷P2678:跳石头(贪心 + 二分)
题目背景 一年一度的"跳石头"比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间 ...
- Educational DP Contest R - Walk(倍增floyd,矩阵快速幂)
题目来源:AtCoder EDU DP题集 题目链接:Here 单独拎出来是因为这道题是一个很好的板子,值得记录 题意 给定一个 n 个节点的有向图的邻接矩阵,求该有向图中长度为 k 的路径长. 解法 ...