在开发完一个类似于prometheus的metrics收集系统软件后,经过n多次debug,软件终于run起来了。因为对于我们的系统,指标不需要非常频繁的获取(事实上对于prometheus而言,也基本都是5秒、10秒或者更长时间的获取时间间隔),所以我首先调整了获取频率到50ms,准备先一次性看一下有没有性能问题。

果不其然,CPU处于合理的范围(30%的样子),但是内存,每秒大几MB的涨,不一会儿就涨到了1G多,这里说的内存时实际使用内存,也就是RES,并不是虚拟内存。而换算来看,节点的数据都还没获取到多少呢。

这明显时不能接受的。因为这个程序会像prometheus一样,作为守护进程长期运行。于是开始调查。利器上来了,pprof。追了一会后,发现是我们存储每个metrics的label_name-label_value的那个map,分配了非常大量的内存,这个内存在本次数据被序列化到文件之前,是常驻的。只能进行优化处理了。(对于pprof关于内存leak的定位和过程,就不在这里赘述了,分享一篇文章:How I investigated memory leaks in Go using pprof on a large codebase)。

找到问题后,没有立即下手对该mmp,哦不对,是map进行开刀,而是仍然感觉即便是频繁的创建,非常不合理。仔细回顾了整个过程,一个细节引起了我的注意。就是由于程序是有很多锁、原子操作、goroutine的较为复杂的程序,在编译时用了-race的选项,以便在运行的时候观察是否有资源的不合理竞争。

马上,将该选项移除后编译运行,内存增速果然急剧下降,这里开心一秒钟。但马上就变脸了,因为观察发现内存的增速还是有点猛。依旧用pprof定位到是该map。

没想到golang的map这么RG,到这里,我总结了下该地方使用map的原因,以及特点:

  1. 该map存储了是metrics的label。对于我们的metrics,目前只有很少的label,而且可预见的未来,也只会有几个,不到5个吧。
  2. 使用map,是为了加快搜索。

想到这,我想到了2种解决方案:
a. 将该map用slice替换,因为存储的数量很少,甚至都可以在搜索的时候暴力遍历,连二分查找都不用;
b. 在一个统一的地方用一个数据结构维护所遇到的所有label name和label value,也可以理解为symbol吧。我们系统的label name就是固定的几个,而label value,感觉顶多也就几千台机器,几万个吧。这个数据结构包含了map[string]uint16和symbols的slice。然后在每个metrics种依然用map,只是不再用string,key和value都换成uint16,指示在slice中的下标。这样,不管是从id找string,还是string找id,都是O(1)的操作。

方案a没有去尝试,但一定是一个非常节省内存的方式。没有尝试的理由是不想引入复杂度和太多的数据结构,暴力搜索又显得不是很优雅。上面分享的那个文章中,采用的是这个方法。
采用了方案b,最终执行下来的结果还是比较满意。
其实具体怎么做,是和业务息息相关的。

总结

  1. golang的map是hash存储,查找速度是O(1)的,但是内部采用了空间换时间的做法,维护2个hash表,再加上一些辅助信息,占用的内存还是挺高的,不建议在程序中被频繁分配且被长时间持有。而且一个比较蛋疼的事情是它不像c++的map,是采用二叉树存储从而做到有序,golang的map是无须的,c++中专门又unorderd_map去做这个事情。使用的时候要注意了,可能会带来一些测试上面的不便捷。
  2. go build -race是个神器,但是它会带来额外的内存和cpu的增长。golang的map是非线程安全的,目前来看,编译器会分配额外的资源去监控这个map。

记一次golang memory leak的解决过程相关推荐

  1. IDEA中记一次BuildProject不好使的解决过程

    场景 IDEA中进行修改部分代码后,需要点击编译按钮Build Project 近期点击后进行控制台就会提示Not Started,输出到一半就不输出了. 只能每次一修改部分代码就得重启项目. 实现 ...

  2. 记一次拉去代码失败的解决过程Permission denied, please try again. git@code.odrcloud.cn: Permission denied

    问题描述: 今天想要从git上拉一份新的代码,首先使用idea拉去,失败报错没有权限,如下图: Cloning into 'xxx'... Permission denied, please try ...

  3. mysql memory leak_解决memory leak问题

    应用程序注册了JDBC驱动,但当程序停止时无法注销这个驱动,tomcat为了防止内存溢出,就给强制注销了 解决: 重写了org.apache.commons.dbcp.BasicDataSource  ...

  4. 一则JVM memory leak解决的过程

    起因是我们的集群应用(3台机器)新版本测试过程中,一般的JVM内存占用 都在1G左右, 但在运行了一段时间后,慢慢升到了4G, 这是一个明显不正常的现象. 定位 过程: 1.先在该机器上按照步骤尝试重 ...

  5. This is very likely to create a memory leak.

    前言 tomcat 7.0.78 java 1.8.0_161 现象 tomcat启动过程中出现如下报错: The web application [/xx/xxx] appears to have ...

  6. 使用LeakTracer检测android NDK C/C++代码中的memory leak

    Memory issue是C/C++开发中比较常遇到,经常带给人比较大困扰,debug起来又常常让人无从下手的一类问题,memory issue主要又分为memory leak,野指针,及其它非法访问 ...

  7. MFCButton Memory leak(内存泄露问题)

    MFCButton Memory leak(内存泄露问题) http://m.blog.csdn.net/blog/haoekin/8851219 1.无法显示右边箭头的问题 无论怎么折腾都没显示不出 ...

  8. 记一次golang中sync.Map并发创建、读取的问题

    记一次golang中sync.Map并发创建.读取的问题  cunfate https://www.jianshu.com/p/f472e79909bc 背景: 我们有一个用go做的项目,其中用到了z ...

  9. 性能优化之内存泄露(Memory Leak)常用分析工具(另3种)

    1 LeakCanary(最常用,能监控整个App内存泄漏情况) 1.1 使用LeakCanary // 仅在debug包启用LeakCanary debugImplementation 'com.s ...

  10. uniapp MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 upgrade listeners

    uniapp 出现这个红色提示语 (node:39268) MaxListenersExceededWarning: Possible EventEmitter memory leak detecte ...

最新文章

  1. hdu 4876 ZCC loves cards(暴力)
  2. android 关闭蓝牙打电话功能,Android蓝牙开发【八】hfp接听、挂断电话
  3. 【Java】图解 Spring 循环依赖,写得太好了
  4. 优秀的程序员是如何诞生的?
  5. 鸿蒙会像IOS,你更看好鸿蒙还是苹果?iOS系统升级 分享与互联成苹果发布会主题...
  6. 中国智慧园区未来发展趋势及投资战略规划研究报告2022年版
  7. docker安装gitlab
  8. 年薪60w的程序员与年薪6w的极品程序员,差距怎么这么大呢?
  9. 经纬度的多种格式和转换方式
  10. 计算机网页设计实习报告怎么写,网页设计实习报告.docx
  11. labview dsn连接mysql_labview使用DSN与数据库的连接包括access,mysql
  12. Lnux-组-用户管理
  13. window10下搭建php的运行环境
  14. 搭建个人博客详细教程
  15. 如何推送PLC报警消息至微信
  16. 学习记录:关于Uniapp与Java实现支付宝沙箱APP内支付
  17. Java编程题之四个数字组成不同且无重复的三位数
  18. 受众同步管理 , 精准再营销
  19. 应用实践:Paddle分类模型大集成者[PaddleHub、Finetune、prompt]
  20. 知乎热议:如何成为中国科学院院士?

热门文章

  1. USB-C PD接口DRP芯片功能介绍
  2. Angular sort descending
  3. 爬取斗鱼主播名字和热度
  4. redis存储新闻列表_聊聊Redis使用场景
  5. 【计算机组成原理】中央处理器总结——基本知识要点汇总
  6. volatility用法
  7. 【kafka专栏】集成apache kafka-clients实现数据消费者
  8. html5调用手机震动
  9. 直播评论可以用html,网页制作HTML5实现直播间评论滚动效果的代码
  10. AMD EPYC(霄龙)Genoa服务器 | 综合评测