Hi, 应用多年的go pprof查看内存透露的办法竟然是错的?!
起个好题目的确能减少访问量

最近在做一个 Redis 的 Proxy 的我的项目,其中利用Redis 6.0 新加的 tracking 性能实现客户端缓存的性能,能够为某些特定的redis应用场景进步吞吐和提早。

当然,cache的实现也是有代价的。首先,cache的大小不能无限度的大,否则总有一点会把内存撑爆的;其次,cache的淘汰算法有多种形式,LRU、LFU等等,具体能够参考Cache replacement policies,不同的场景下各种淘汰算法的成果是不一样的;第三,对于大并发状况实现cache是有代价的,因为并发状况下对cache的拜访须要加锁,而加锁就意味着有性能的损失。

我在实现这个cache的过程中略微偷了一下懒, 想尽量的缩小锁的scope,后果导致内存透露的问题。原本cache占用的最大内存我设置为10GB, 后果过了个周末发现程序曾经占用了80GB的内存了。

当然本文不是要介绍这个我的项目的内存透露起因,而是介绍一下Go pprof工具查找内存透露的一个不太罕用的办法。

查看Go程序内存的应用状况最罕用的就是Go规范库自带的pprof库了,能够通过http暴露出这个profile, 而后通过go tool pprof或者pprof工具命令行/web形式查看。

比方上面的命令, 能够获取服务器http://ip:port的堆信息,并且在本机9090端口启动一个服务器展现堆的信息。

go tool pprof -http :9090 http://ip:port/debug/pprof/heap

在堆信息中你能够查看调配的堆的大小和对象数量,或者以后没有开释的占用的堆的大小和对象数量。

失常状况下应用这个形式就能够比拟直观的看到哪一段代码调配的内存比拟多,而后确定那里容易产生内存透露。

然而, 调配堆内存比拟多的中央并不一定产生内存透露,只能阐明这个中央"已经/正在"调配的堆内存比拟大,或者调配的堆内存比拟频繁俄安,这些调配的内存可能在之后就回收掉了。

像Java的一些profiler工具一样, pprof也能够比拟两个工夫点的调配的内存的差值,通过比拟差值,就容易看到哪些地方产生的内存"残留"的比拟多,没有被内存开释,极有可能是内存透露的点。

你能够通过上面的形式产生两个工夫点的堆的profile,之后应用pprof工具进行剖析。

  1. 首先确保你曾经配置了pprof的http门路, 能够拜访http://ip:port/debug/pprof/查看(如果你没有批改默认的pprof门路)
  2. 导出工夫点1的堆的profile: curl -s http://127.0.0.1:8080/debug/p... > base.heap, 咱们把它作为基准点
  3. 喝杯茶,期待一段时间后导出工夫点2的堆的profile: curl -s http://127.0.0.1:8080/debug/p... > current.heap
  4. 当初你就能够比拟这两个工夫点的堆的差别了: go tool pprof --base base.heap current.heap

操作和失常的go tool pprof操作一样, 比方应用top查看应用堆内存最多的几处中央的内存增删状况:

应用web命令会生成一个SVG文件,可能你须要应用浏览器关上它。

或者你间接应用命令关上web界面: go tool pprof --http :9090 --base base.heap current.heap

原文地址:
https://colobu.com/2019/08/20...

关注获取更多好文

本文由mdnice多平台公布