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 ...
随机推荐
- 边缘AI方案落地问题探讨
摘要:本文介绍了如何兑现边缘AI带来好处的承诺,并针对边缘AI落地和商业闭环发起的开源社区工作. 本文分享自华为云社区<华为云:边缘AI方案落地问题探讨及调研>,作者: 华为云边缘云创新实 ...
- 浏览器史话中chrome霸主地位的奠定与国产浏览器的割据混战
作为前端老鸟,从IE的6.7.8开始做前端,各种兼容性折磨死人.js还好有了jQuery.chrome出来后,真是救苦救难,解救程序员的于水火.但是可恶的boss还是要求兼容ie6,7.感谢淘宝团队的 ...
- DevEco中被忽略的实用功能
近期,我一直在业余时间研究纯血鸿蒙(HarmonyOS)App的开发,所使用的IDE是华为官方的DevEco Studio 3.1.1. 随着使用时间的增长,我发现了几个特别容易被忽略,但又特别实用的 ...
- 透析阿里云视频云「低代码音视频工厂」之能量引擎——vPaaS 视频原生应用开发平台
为满足企业用户极速搭建高品质专属音视频业务的需求,阿里云视频云的"低代码音视频工厂"应运而生,但极速而高品质的平台搭建诉求,需要用全新的开发方式才能真正实现,而全新的开发方式背后蕴 ...
- MongoDB 和 MySQL 之间有何区别?
MongoDB 和 MySQL 是两个可用于存储和管理数据的数据库管理系统.MySQL 是一个关系数据库系统,以结构化表格格式存储数据.相比之下,MongoDB 以更灵活的格式将数据存储为 JSON ...
- mybatisplus 查询结果排除某字段实现
数据有Test表,表里有id,name,ip_address,last_time四个字段 通常查询写法,返回结果会把id,name,ip_address,last_time四个字段都返回 public ...
- js滑动验证
https://gitee.com/anji-plus/captcha AjCaptcha验证码: https://blog.csdn.net/zbchina2004/article/details/ ...
- shell读取配置文件中的参数
shell读取配置文件中的参数 配置文件 配置文件config.properties如下: user=bk age=25 ip=192.168.37.1 一.使用cat+awk语句过滤并赋值变量 u ...
- docker 容器ip查看及 网络配置区别
本文为博主原创,未经允许不得转载: 1. 查看容器ip: 方法一:查看所有容器的ip docker inspect --format='{{.Name}} - {{range .NetworkSett ...
- webflux 的使用总结
本文为博主原创,未经允许不得转载: 1. Servlet 3.0 简介 2. WebFlux 简介 及 特点 3. 基于函数式的 WebFlux 开发 4. webFlux 全局异常 5. webF ...
