重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]( 二 )


文章插图
那么我们知道 , 第二次转储文件的时候内存是上述了的 。
那么同样的操作在第二个里面执行:
lldb --core /tmp/coredump.manual.2.108232setthread 15dso

重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这里已经变成了string[]
用dumparray 00007f48e538a4b0 查看一下这个string[] 对象是啥?
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
看下第一个的string 对象的情况:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
读取一下内存:
memory read -c 384 00007f48c3bc8f68
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这里就基本确认问题了 。
但是这样去定位问题 , 其实是有点慢的 。而且发现 , 这个定位在cpu 倒是一个不错的选择 , 但是定位内存显得不那么合理 。
因为cpu不高的情况 , 但是内存高的情况 , 这个时候肯定就是有很多碎片没有回收 , 上面查的情况是根据执行去判断的 。
统计的方法定位问题是比较快的 。
两个里面查看统计:
dumpheap -stat第一个:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
第二个:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
发现这个system.string 两个都很大 , 且变多了 , 而DataRow 也不少 。
但是这里涨的又不成比例 , 比如这里对象涨了几百 , 但是内存涨了200m 。
这个时候可能就怀疑 大型对象堆 (LOH) 的问题了 。
那么查一下大于85000字节的数据统计 。
dumpheap -stat -min 85000
第一个:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
第二个:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
运行 dumpheap -stat -min 85000 -live 。此命令仅显示根于某处的对象 。在此示例中 , 只有正确的对象实例 string 位于 LOH 中 。
-live 就是活跃的意思 , 也就是应用程序正在使用的 , 不会被GC的 。
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这里有4个 , 看下这4个是啥吧 。
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
然后查看一个的内存:
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这样就定位到了 。
但是还得查看一下这个对象位置在哪? 怎么办呢?用SOS的命令:gcroot
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这个是源代码内部的 , 看的不清楚 。
使用-all
重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]

文章插图
这样就直接定位到行了 。
原因就是string+=string , 等于String.Concat(System.String[])造成大量string 对象复制堆积 。
结下一节介绍procDump 和 dotnet-dump , procDump 这个挺好用的 , dotnet-dump 更为方便 。基本是必学的 。
【重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]】

经验总结扩展阅读