当前位置: 首页 > news >正文

【博客714】golang使用mmap来优化gc

golang使用mmap来优化gc:

背景

需要处理的对象非常多时,比如:时序数据库victoriametrics源码中,利用了mmap申请内存并自己维护,从而避免过多gc影响性能,因为频繁申请和释放堆对象会降低性能

参考victoriametrics malloc_mmap.go

example

package mainimport ("flag""fmt""runtime""runtime/debug""time""golang.org/x/sys/unix"
)const size = 3 * 1024 * 1024 * 1024 // 3GB
const hello = "hello"func allocateMemory(useMmap bool) []byte {if useMmap {data, err := unix.Mmap(-1, 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_ANON|unix.MAP_PRIVATE)if err != nil {fmt.Println("Error creating memory mapping:", err)return nil}// 将 "hello" 写入满整个内存for i := 0; i < size; i += len(hello) {copy(data[i:min(i+len(hello), size)], []byte(hello))}return data}// 使用 make 分配内存并写入满整个内存data := make([]byte, size)for i := 0; i < size; i += len(hello) {copy(data[i:min(i+len(hello), size)], []byte(hello))}return data
}func min(a, b int) int {if a < b {return a}return b
}// 打印 GC 统计信息和当前内存情况
func printGCStatsAndMemoryInfo(label string, data []byte) {var stats debug.GCStatsdebug.ReadGCStats(&stats)var memStats runtime.MemStatsruntime.ReadMemStats(&memStats)fmt.Printf("%s GC Stats: LastGC=%v, NumGC=%d, PauseTotal=%v\n", label, stats.LastGC, stats.NumGC, stats.PauseTotal)fmt.Printf("%s Memory Stats: Alloc=%v, TotalAlloc=%v, Sys=%v, NumGC=%v\n", label, memStats.Alloc, memStats.TotalAlloc, memStats.Sys, memStats.NumGC)fmt.Printf("%s Current Memory: %v bytes\n", label, len(data))
}func main() {useMmap := flag.Bool("usemmap", false, "Specify whether to use mmap for memory allocation (default: false)")flag.Parse()if *useMmap {fmt.Println("Using mmap for memory allocation")} else {fmt.Println("Not using mmap for memory allocation")}// 定期打印 GC 执行情况和当前内存情况ticker := time.NewTicker(2 * time.Second)defer ticker.Stop()data := allocateMemory(*useMmap)defer func() {if *useMmap {unix.Munmap(data)}}()for {select {case <-ticker.C:// 每隔2秒打印一次printGCStatsAndMemoryInfo("Current", data)}}
}

使用go的堆内存:看到当前的内存占用了3G,且go的gc感知到这部分的,所以gc需要扫的内存是很多的,而这部分是常驻的话又不会被回收,所以导致不必要的gc压力

[root@ ~]# ./gc-test
Not using mmap for memory allocation
Current GC Stats: LastGC=2024-01-29 15:10:45.747195763 +0800 CST, NumGC=1, PauseTotal=185.526µs
Current Memory Stats: Alloc=3221337272, TotalAlloc=3221338128, Sys=3283418896, NumGC=1
Current Current Memory: 3221225472 bytes
Current GC Stats: LastGC=2024-01-29 15:10:45.747195763 +0800 CST, NumGC=1, PauseTotal=185.526µs
Current Memory Stats: Alloc=3221355080, TotalAlloc=3221355936, Sys=3283418896, NumGC=1
Current Current Memory: 3221225472 bytes
...
...使用top看其实都占用了3G:PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND319166 root      20   0 4425716   3.1g   1320 S   0.0  19.9   0:05.94 gc-test

使用mmap:看到虽然当前的内存占用了3G,但是go的gc感知不到这部分的,所以gc需要扫的内存是很少的

[root@ ~]# ./gc-test -usemmap
Using mmap for memory allocation
Current GC Stats: LastGC=1970-01-01 08:00:00 +0800 CST, NumGC=0, PauseTotal=0s
Current Memory Stats: Alloc=105856, TotalAlloc=105856, Sys=7183376, NumGC=0
Current Current Memory: 3221225472 bytes
Current GC Stats: LastGC=1970-01-01 08:00:00 +0800 CST, NumGC=0, PauseTotal=0s
Current Memory Stats: Alloc=122184, TotalAlloc=122184, Sys=7183376, NumGC=0
Current Current Memory: 3221225472 bytes
...
...使用top看其实都占用了3G:PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND319179 root      20   0 4372212   3.0g   1320 S   0.0  19.6   0:05.23 gc-test

结论:虽然在go堆内分配内存和使用mmap分配内存在进程外的视角是一样的,但是在go runtime视角上,是看不到mmap这部分的,所以不会去进行gc扫描的,可以减轻压力
所以对于常驻大内存使用mmap性能更高,但是要自己维护好分配和释放,否则会导致内存泄漏

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 从零开始学Vue3--环境搭建
  • AUTOMATIC1111/stable-diffusion-webui/stable-diffusion-webui-v1.9.3
  • 【FPGA】Verilog:解码器 | 编码器 | 多路复用器(Mux, Multiplexer)
  • 基于HTML5和CSS3搭建一个Web网页(二)
  • 本地部署Whisper实现语言转文字
  • 2024年【N1叉车司机】免费试题及N1叉车司机模拟试题
  • Spring服务启动后就执行某个方法
  • Alienware外星人笔记本m17 R3原厂OEM预装Win10系统包下载,恢复开箱状态电脑自带系统
  • python 多线程处理图片
  • 【算法】前缀和——寻找数组的中心下标
  • 【2024最新华为OD-C卷试题汇总】传递悄悄话的最长时间(100分) - 三语言AC题解(Python/Java/Cpp)
  • 杰理-耳机进入关机关闭内内置触摸-节省功耗
  • 数据结构_链式二叉树(Chained binary tree)基础
  • 什么是JDK21虚拟线程
  • gc和gccgo编译器
  • 时间复杂度分析经典问题——最大子序列和
  • EOS是什么
  • XML已死 ?
  • 飞驰在Mesos的涡轮引擎上
  • 给第三方使用接口的 URL 签名实现
  • 老板让我十分钟上手nx-admin
  • 前端代码风格自动化系列(二)之Commitlint
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 数组的操作
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 容器镜像
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • #pragma预处理命令
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (HAL库版)freeRTOS移植STMF103
  • (八)Flink Join 连接
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (全注解开发)学习Spring-MVC的第三天
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • .htaccess配置重写url引擎
  • .NET Core 版本不支持的问题
  • .NET DataGridView数据绑定说明
  • .net连接MySQL的方法
  • // an array of int
  • /etc/sudoer文件配置简析
  • :=
  • @RequestParam详解
  • [012-1].第12节:Mysql的配置文件的使用
  • [android]-如何在向服务器发送request时附加已保存的cookie数据
  • [Android开源]EasySharedPreferences:优雅的进行SharedPreferences数据存储操作
  • [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
  • [Grafana]ES数据源Alert告警发送
  • [IE技巧] 让IE 以全屏模式启动
  • [iOS]中字体样式设置 API
  • [NKCTF 2024]web解析
  • [office] 如何在Excel中拉动单元格时表头不变形- #学习方法#职场发展#经验分享