之前InCerry(如下是InCerry同学的公众号)等社区同学翻译了一系列.NET性能分析相关的博客,原作者是Maoni Stephens等人,近期发现了相关内容被合入到如下仓库中,大家可以点击公众号左下角的《阅读原文》来查看详细内容,本公众号也将分享(转载)相关内容。
https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md
——————————如下是原文内容:————————————
知道什么时候该担心,以及在需要担心的时候该怎么做。
本文档的目的
本文旨在帮助 .NET 开发者,如何思考内存性能分析,并在需要时找到正确的方法来进行这种分析。本文中的 .NET 包括 .NET Framework 和 .NET Core。为了在垃圾收集器和框架的其他部分获得最新的内存改进,我强烈建议你使用 .NET Core,因为 .NET Core 有更积极活跃的开发进展。
本文档的状态
这是一份持续迭代的文档。现在,这份文档主要关注 Windows 方面。添加 Linux 方面的材料肯定会使它更有用。我计划在不久的将来处理这方面的事情,同时也非常欢迎其他人对该文件的贡献(尤其是对 Linux 部分)。
版本修订历史记录
版本号 | Commit | 注解 |
1.0 | c006800[1] | 在这之前,我没有维护版本历史,但我们很快就会有一个中文版本签入 - 为了使两个文档保持同步,我们需要一个版本历史。 |
如何阅读本文档
这是一份很长的文档,你不需要阅读它的全部内容;你也无需严格按顺序阅读各章节。根据你从事性能分析方面的经验,有些章节可以完全跳过。
🔹 如果你对性能分析工作完全陌生,我建议从头开始。
🔹 对于那些已经能轻松应对大部分的性能分析工作,但希望进一步了解托管内存相关知识的人,可以跳过开头,直接进入基础知识[2]部分。
🔹 如果你不是很有经验,并且在做一次性的性能分析,你可以跳到知道什么时候该担心[3]部分开始阅读,如果需要,再参考基础知识[4]部分的具体内容。
🔹 如果你是一名性能工程师,且托管内存分析是你的一项常规任务,但不太熟悉 .NET,我强烈建议你认真阅读并消化GC基础[5]部分,因为它能帮助你更快地关注正确的事情。然而,如果你手头有一个紧急问题,你可以去看看我在本文档中将要使用的工具[6],熟悉它,然后看看你是否能在GC暂停问题[7]或堆大小问题[8]部分找到相关症状。
🔹 如果你已经有做托管内存性能分析工作的经验,并且有具体的问题,你可以在GC停顿时间长[9]或GC堆太大[10]部分找到你想要的内容。
注意!
当我在写这篇文档时,我打算根据分析的需要来介绍一些概念,如并发的GC或钉住。所以在你阅读的过程中,你会逐渐接触到它们。如果你已经知道它们是什么,并且正在寻找关于特定概念的解释,这里有它们的链接-
分配预算[11]
并发GC/后台GC[12]
终结器[13]
分代GC[14]
LOH (LOH-Large-Object-Heap 大对象堆)[15]
钉住[16]
服务器GC[17]
内容
如何看待性能分析工作?[18]
挑选正确的方法来做性能分析[19]
◼️知道你的目标是什么[20]
◼️你要明白GC只是框架的一个部分[21]
◼️不要猜测,去测量[22]
◼️足够的测量,让你知道应该把精力集中在哪个领域[23]
◼️测量那些可能影响你的性能指标的因素[24]
◼️优化框架代码与优化用户代码[25]
内存基础知识[26]
◼️虚拟内存基础知识[27]
◼️GC基础[28]
▪️了解GC堆内存的使用与进程/机器内存的使用情况[29]
•GC堆只是你进程中的一种内存使用情况[30]•GC是按进程进行的,但它知道机器上的物理内存负载[31]
▪️了解GC是如何被触发的[32]
•触发GC的主要原因是分配[33]•触发GC的其他因素[34]
▪️了解分配内存的成本[35]
▪️如何正确看待GC堆的大小[36]
•看一下GC堆的大小与GC发生的时间关系[37]•分配预算[38]•分代GC的影响[39]•碎片化(自由对象)是堆大小的一部分[40]•GC自己的记账[41]•什么时候GC会抛出一个OOM异常?[42]
▪️了解GC暂停-即何时触发GC以及GC持续多长时间)[43]
•单个GC的持续时间[44]•多长时间触发一次GC?[45]•要记住的一条规则[46]•是什么使一个对象得以存活[47]1-分代方面[48]2-用户根[49]3-托管内存泄漏[50]•“主线GC场景” vs “非主线”[51]•完全不做GC工作的部分 GC暂停 — 线程挂起[52]
知道什么时候该担心[53]
◼️顶层应用指标[54]
◼️顶层的GC指标[55]
◼️何时应担心GC[56]
挑选正确的工具和解释数据[57]
◼️性能工具一览[58]
◼️我们使用的工具以及它是如何完成工作的[59]
◼️如何开始进行内存性能分析[60]
◼️如何收集顶层的GC指标[61]
◼️显示顶级的GC指标[62]
◼️PerfView中的其他相关视图[63]
◼️GC暂停时间百分比高[64]
▪️太多的停顿,即太多的GC[65]
•测量分配[66]•理解为什么GC决定收集这一代[67]
▪️个别的长时间停顿[68]
•首先,您是否存在托管内存泄漏?[69]•长时间的停顿是由于短暂的GCs、完全阻塞的GCs还是BGCs?[70]•计算出gen2 GC的工作量[71]•计算出短暂GC的工作量[72]•弄清楚长的GC是否是由于GC工作造成的[73]
◼️大尺寸的GC堆[74]
•调试OOM[75]•峰值尺寸太大,但GC后尺寸不大?[76]•GC后尺寸很大?[77]•gen2 GC是否主要为后台GC?[78]•你看到的堆的大小从GC的角度来看是合理的,但仍然希望有一个更小的堆?[79]•GC是否为自己的记账工作使用了太多的内存?[80]
性能问题的明确迹象[81]
◼️暂停时间太长[82]
◼️随机的长时间GC停顿[83]
◼️大多数GC是完全阻塞的GC[84]
有助于我们帮助你调试性能问题的信息[85]
◼️运行时的文件版本[86]
◼️你已经进行了哪些诊断[87]
◼️性能数据[88]
References
[1]
c006800: https://github.com/Maoni0/mem-doc/commit/c006800d5173d8b4da60faebe94bc5b724f32cfd[2]
基础知识: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#内存基础知识[3]
知道什么时候该担心: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#知道什么时候该担心[4]
基础知识: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#内存基础知识[5]
GC基础: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC基础[6]
工具: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#我们使用的工具以及它是如何完成工作的[7]
GC暂停问题: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC暂停时间百分比高[8]
堆大小问题: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#大尺寸的GC堆[9]
GC停顿时间长: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC暂停时间百分比高[10]
GC堆太大: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#大尺寸的GC堆[11]
分配预算: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#分配预算[12]
并发GC/后台GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#并发GC后台GC[13]
终结器: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#终结器[14]
分代GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#分代GC的影响[15]
LOH (LOH-Large-Object-Heap 大对象堆): https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#大对象堆[16]
钉住: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#钉住[17]
服务器GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#服务器GC[18]
如何看待性能分析工作?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#如何看待性能分析工作[19]
挑选正确的方法来做性能分析: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#挑选正确的方法来做性能分析[20]
知道你的目标是什么: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#知道你的目标是什么[21]
你要明白GC只是框架的一个部分: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#你要明白GC只是框架的一个部分[22]
不要猜测,去测量: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#不要猜测去测量[23]
足够的测量,让你知道应该把精力集中在哪个领域: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#足够的测量让你知道应该把精力集中在哪个领域[24]
测量那些可能影响你的性能指标的因素: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#测量那些可能影响你的性能指标的因素[25]
优化框架代码与优化用户代码: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#优化框架代码与优化用户代码[26]
内存基础知识: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#内存基础知识[27]
虚拟内存基础知识: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#虚拟内存基础知识[28]
GC基础: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC基础[29]
了解GC堆内存的使用与进程/机器内存的使用情况: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#了解GC堆内存的使用与进程机器内存的使用情况[30]
GC堆只是你进程中的一种内存使用情况: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC堆只是你进程中的一种内存使用情况[31]
GC是按进程进行的,但它知道机器上的物理内存负载: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC是按进程进行的但它知道机器上的物理内存负载[32]
了解GC是如何被触发的: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#了解GC是如何被触发的[33]
触发GC的主要原因是分配: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#触发GC的主要原因是分配[34]
触发GC的其他因素: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#触发GC的其他因素[35]
了解分配内存的成本: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#了解分配内存的成本[36]
如何正确看待GC堆的大小: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#如何正确看待GC堆的大小[37]
看一下GC堆的大小与GC发生的时间关系: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#看一下GC堆的大小与GC发生的时间关系[38]
分配预算: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#分配预算[39]
分代GC的影响: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#分代GC的影响[40]
碎片化(自由对象)是堆大小的一部分: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#碎片化自由对象是堆大小的一部分[41]
GC自己的记账: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC自己的记账[42]
什么时候GC会抛出一个OOM异常?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#什么时候GC会抛出一个OOM异常[43]
了解GC暂停-即何时触发GC以及GC持续多长时间): https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#了解GC暂停即何时触发GC以及GC持续多长时间[44]
单个GC的持续时间: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#单个GC的持续时间[45]
多长时间触发一次GC?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#多长时间触发一次GC[46]
要记住的一条规则: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#要记住的一条规则[47]
是什么使一个对象得以存活: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#是什么使一个对象得以存活[48]
1-分代方面: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#1-分代方面[49]
2-用户根: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#2-用户根[50]
3-托管内存泄漏: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#3-托管内存泄漏[51]
“主线GC场景” vs “非主线”: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#主线GC场景-vs-非主线[52]
完全不做GC工作的部分 GC暂停 — 线程挂起: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#完全不做-gc-的部分-gc-暂停线程挂起-[53]
知道什么时候该担心: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#知道什么时候该担心[54]
顶层应用指标: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#顶层应用指标[55]
顶层的GC指标: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#顶层的GC指标[56]
何时应担心GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#何时应担心GC[57]
挑选正确的工具和解释数据: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#挑选正确的工具和解释数据[58]
性能工具一览: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#性能工具一览[59]
我们使用的工具以及它是如何完成工作的: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#我们使用的工具以及它是如何完成工作的[60]
如何开始进行内存性能分析: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#如何开始进行内存性能分析[61]
如何收集顶层的GC指标: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#如何收集顶层的GC指标[62]
显示顶级的GC指标: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#显示顶级的GC指标[63]
PerfView中的其他相关视图: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#PerfView中的其他相关视图[64]
GC暂停时间百分比高: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC暂停时间百分比高[65]
太多的停顿,即太多的GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#太多的停顿即太多的GC[66]
测量分配: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#测量分配[67]
理解为什么GC决定收集这一代: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#理解为什么GC决定收集这一代[68]
个别的长时间停顿: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#个别的长时间停顿[69]
首先,您是否存在托管内存泄漏?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#首先您是否存在托管内存泄漏[70]
长时间的停顿是由于短暂的GCs、完全阻塞的GCs还是BGCs?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#长时间的停顿是由于短暂的GCs完全阻塞的GCs还是BGCs[71]
计算出gen2 GC的工作量: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#计算出gen2-GC的工作量[72]
计算出短暂GC的工作量: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#计算出短暂GC的工作量[73]
弄清楚长的GC是否是由于GC工作造成的: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#弄清楚长的GC是否是由于GC工作造成的[74]
大尺寸的GC堆: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#大尺寸的GC堆[75]
调试OOM: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#调试OOM[76]
峰值尺寸太大,但GC后尺寸不大?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#峰值尺寸太大但GC后尺寸不大[77]
GC后尺寸很大?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC后尺寸很大[78]
gen2 GC是否主要为后台GC?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#gen2-GC是否主要为后台GC[79]
你看到的堆的大小从GC的角度来看是合理的,但仍然希望有一个更小的堆?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#你看到的堆的大小从GC的角度来看是合理的但仍然希望有一个更小的堆[80]
GC是否为自己的记账工作使用了太多的内存?: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#GC是否为自己的记账工作使用了太多的内存[81]
性能问题的明确迹象: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#性能问题的明确迹象[82]
暂停时间太长: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#暂停时间太长[83]
随机的长时间GC停顿: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#随机的长时间GC停顿[84]
大多数GC是完全阻塞的GC: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#大多数GC是完全阻塞的GC[85]
有助于我们帮助你调试性能问题的信息: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#有助于我们帮助你调试性能问题的信息[86]
运行时的文件版本: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#运行时的文件版本[87]
你已经进行了哪些诊断: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#你已经进行了哪些诊断[88]
性能数据: https://github.com/Maoni0/mem-doc/blob/master/doc/.NETMemoryPerformanceAnalysis.zh-CN.md#性能数据