corner imagecorner image FeaturesPluginsPlatformDocs & SupportCommunityPartners

内存性能分析的不完全统计数据

内存性能分析的不完全统计数据收集

Profiler 提供的每个类的已分配对象的总数(在“仅记录对象创建”和“记录对象创建和垃圾回收”两种模式下)是准确数字,而其他数字(如对象总大小)和反向调用图形缺省情况下都是以统计方式获得的。这是 Profiler 中提供的众多性能改进措施之一。

收集统计数据的工作方式如下:每种分析的类型(类或数组)都具有一个关联的计数器,其初始值为 10(可以在“分析内存使用情况”命令对话框或定制内存性能分析中更改缺省值)。每分配一个给定类的实例,计数器的值就会递减一次。当它达到零时,将确定已分配对象的大小,进行栈跟踪并再次为计数器分配初始值。Profiler 显示的对象分配反向调用图形就是根据这些栈跟踪绘制的,而 Profiler 报告的对象总大小只是进行了栈跟踪的那些对象的总大小。

还请注意,在分配调用图形中看到的方法调用次数与在 CPU 性能分析中看到的方法调用次数不同。在进行内存性能分析时,这些次数并不是实际调用给定方法的次数,而是在给定上下文的栈上发现此方法时进行的栈跟踪次数。因此,您可能会发现 main 应用程序方法包含多个调用。事实上,如果应用程序是单线程的,则为 main 方法显示的“调用”总数与进行的栈跟踪总数是相同的。

当然,使用统计数据收集时,其中的某些调用路径的相关信息就会丢失。然而,实际确定最活跃的对象分配位置和调用路径通常是很重要的。即使使用上述统计栈抽样的方法,这些信息也是很明显的。如果要收集有关调用路径的确切信息,只需将栈抽样间隔值设置为 1 即可。不过,这可能会导致性能显著下降。为了在所收集信息的准确性与性能影响之间找到合理的折衷方案,缺省栈抽样间隔被设置为 10。

另请注意,在此类性能分析中,Profiler 不会严格使用固定的栈抽样间隔。这样做是为了避免不希望的数据关联。例如,如果程序包含一个循环,它在方法 foo() 中连续分配 9 个 X 实例,然后在方法 bar() 中分配一个实例,如果严格遵循每分配 10 次 X 时进行栈抽样,结果可能是只获取了在 bar() 中进行的分配的相关信息,而没有获取在 foo() 中进行的分配的任何相关信息,这将是一个相当失真的结果。要纠正这种问题,Profiler 每次进行栈跟踪后,都会将对象分配计数器设置为与用户定义值略有差异的随机值。如果定义的间隔是 10,Profiler 运行时计数器的实际起始值可能类似于 8、11、10、7、9、12 等。通过这种方式,可以确保最终显示的信息在统计学上是可靠的。

另请参见

 

Project Features

About this Project

Profiler was started in November 2009, is owned by Tomas Hurka, and has 41 members.
 
 
Close
loading
Please Confirm
Close