我是一个着迷于产品和运营的技术人,乐于跨界的终身学习者。欢迎关注我的个人公众号「跨界架构师」
每周五11:45 按时送达
我的第「223」篇原创敬上
大家好,我是Z哥。
最近系统在压测过程中发现有一个程序在压力增大后会内存溢出。正好之前自己对 Golang 里分析 dump 这块还没怎么涉及,借此契机学习一下。
网上搜了很多资料,发现 Golang 好像没有手动创建 dump 文件的方式(像 Java 的 jmap,.Net 的创建转储文件这种)。
要么通过设置环境变量,在程序 crash 的时候自动创建 dump 文件,要么程序里 import 一个 pprof 的 package,实时分析 dump 相关的信息。
如果有哪位老司机知道手动创建 dump 的方式,请在评论区教下大家,感谢~
下面我手把手教大家如何通过以上两种方式来分析内存溢出问题,步骤详细,包教包会,建议收藏~
pprof 全称是 performance profiles,是 google 官方提供的性能分析工具,项目地址:https://github.com/google/pprof。配合 Graphviz 使用可以提供图形化的能力。
使用它的方式很简单,配合 pprof 库来使用。只要在代码里增加两块代码。一块是 import:
_"net/http/pprof"
另一块是main函数的开头部分
go func() {
http.ListenAndServe("0.0.0.0:8899",nil)//ip和端口可以更换
}()
然后就可以在浏览器里输入 http://localhost:8899/debug/pprof/ 看到相关的性能维度

上图中框出的这 4 个部分应该是平时最常用的,从上往下分别是:
1.阻塞分析。比如,goroutine 的 wait。
2.内存分析。比如,内存泄漏、内存消耗异常等情况。
3.互斥锁分析。比如,观察代码里用到的 sync.RWMutex 和 sync.Mutex 的具体情况。
4.CPU 分析。比如,排查哪些代码较多地占用了 CPU 资源。
虽然直接在浏览器页面上也能看到一些信息,但是用来分析是不够的,想要真正能分析问题还得通过前面提到的 pprof 工具。
使用 go tool pprof 分析数据,有两种方式:
■ 通过url。go tool pprof http://localhost:8899/debug/pprof/profile
■ 通过文件。go tool pprof cpuprofile 文件路径
好了,我们来试一下。
Z哥写了一段消耗内存的代码,如下:
func main() {
go func() {
http.ListenAndServe("0.0.0.0:8899", nil)
}()
str := "sadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasfsadasdasffrgrgrgrgrgrfefafasf"
for i := 0; i < 999; i++ {
str += str
}
fmt.Scanln()
}
在 web 页面点击「heap」入口,我们可以看到实时内存的使用情况。

然后我们再通过以下命令进入到命令交互模式看看效果:
go tool pprof http://localhost:8899/debug/pprof/heap
进去之后输入「top」,就能很直观的看到哪个方法占用了内存。

这里的几个列的含义简单罗列下:
1.flat:当前函数所占用的容量。
2.flat%:当前函数所占用的容量,在总分配容量的百分比。
3.sum%:是从调用的最外层到当前方法累加使用的容量占总容量的百分比
4.cum:当前函数以及子函数所占用的容量。
5.cum%:当前函数以及子函数所占用的容量,在总分配容量的百分比。
6.最后一列是函数的名字
我们可以再输入获得更详细的信息:
list main.main

每一行代码占用了多少容量直接给你罗列出来了,是不是很香。
分析其他的也是类似的,比如以下是分析 CPU 的。

大多数时候,我们可能没有条件实时分析程序运行情况。比如问题在生产环境偶发出现,且无法在测试环境重现。
这个时候我们可以配置当程序 crash 的时候自动保存 dump 文件。
先输入命令「ulimit -a」看下当前是否开启了core file。

如果是0的话说明未开启。可以通过:
ulimit -c 1024 或者 ulimit -c unlimited 来设置 dump 文件的最大 size。
这里的数字单位是 block,具体需要根据所在的操作系统一个 block 对应的大小来设置。
如果你想让这个设置永久生效那么需要将它添加到 /.profile 中
echo "ulimit -c unlimited" >> ~/.profile
再看下 Golang 的环境变量 GOTRACEBACK 的设置是什么,
export
如果不是 crash 或者不存在 GOTRACEBACK 的环境变量(默认是 none)的话,改成 crash。
export GOBACTRACE=crash
这就意味着,让程序发生 crash 的时候会自动生成 dump 文件。(Z哥在 mac 系统上运行没能自动生成 dump 文件,但在 centos 上可以)
然后运行的程序如果发生 panic,会自动生成 dump 文件在程序运行的目录下。

红框圈出来的是它的默认文件名的格式。
同unlimited 一样,也需要让这个设置永久生效的话,需要添加到/.profile中
echo "export GOTRACEBACK=crash " >> ~/.profile
有了 dump 文件,你就可以用 gdb 或者 delve 工具来分析了(官方更建议我们使用 delve,对 Golang 的支持更好),这里就先不展开了。
一般来说,建议大家如果在本地环境的话使用 pprof 就好了,如果在服务器上,务必开始 crash 自动保存 dump 的功能,便于后续的快速定位问题并分析。
好了,这篇呢,Z 哥和你分享了在 Golang 中分析运行时的代码问题。主要有两种途径:
■ 通过 pprof 实时分析。
■ 程序 crash 时自动保存 dump,再通过 delve 或者 gdb 分析。
希望对你有所帮助。建议收藏,以防不备之需~
推荐阅读:
如果你喜欢这篇文章,可以点一下右下角的「爱心」,支持我的创作~
定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些深度思考。
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
目录0专栏介绍1平面2R机器人概述2运动学建模2.1正运动学模型2.2逆运动学模型2.3机器人运动学仿真3动力学建模3.1计算动能3.2势能计算与动力学方程3.3动力学仿真0专栏介绍?附C++/Python/Matlab全套代码?课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。?详情:图解自动驾驶中的运动规划(MotionPlanning),附几十种规划算法1平面2R机器人概述如图1所示为本文的研究本体——平面2R机器人。对参数进行如下定义:机器人广义坐标
网站的日志分析,是seo优化不可忽视的一门功课,但网站越大,每天产生的日志就越大,大站一天都可以产生几个G的网站日志,如果光靠肉眼去分析,那可能看到猴年马月都看不完,因此借助网站日志分析工具去分析网站日志,那将会使网站日志分析工作变得更简单。下面推荐两款网站日志分析软件。第一款:逆火网站日志分析器逆火网站日志分析器是一款功能全面的网站服务器日志分析软件。通过分析网站的日志文件,不仅能够精准的知道网站的访问量、网站的访问来源,网站的广告点击,访客的地区统计,搜索引擎关键字查询等,还能够一次性分析多个网站的日志文件,让你轻松管理网站。逆火网站日志分析器下载地址:https://pan.baidu.
一、机器人介绍 此处是基于MATLABRVC工具箱,对ABB-IRB-1200型号的微型机械臂进行正逆向运动学分析,并利Simulink工具实现对机械臂进行具有动力学参数的末端轨迹规划仿真,最后根据机械模型设计Simulink-Adams联合仿真。 图1.ABBIRB 1200尺寸参数示意图ABBIRB 1200提供的两种型号广泛适用于各作业,且两者间零部件通用,两种型号的工作范围分别为700 mm 和 900 mm,大有效负载分别为 7 kg 和5 kg。 IRB 1200 能够在狭小空间内能发挥其工作范围与性能优势,具有全新的设计、小型化的体积、高效的性能、易于集成、便捷的接
目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'
我想使用ruby-prof和JMeter分析Rails应用程序。我对分析特定Controller/操作/或模型方法的建议方法不感兴趣,我想分析完整堆栈,从上到下。所以我运行这样的东西:RAILS_ENV=productionruby-prof-fprof.outscript/server>/dev/null然后我在上面运行我的JMeter测试计划。然而,问题是使用CTRL+C或SIGKILL中断它也会在ruby-prof可以写入任何输出之前杀死它。如何在不中断ruby-prof的情况下停止mongrel服务器? 最佳答案
在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_