在上一篇博客使用PerfView监测.NET程序性能(二):Perfview的使用中,我们通过Perfview帮助文件中自带的代码来简单使用了Perfview,了解了基本操作。现在来看看Perfview中的分组操作(Grouping)。分组功能都旨将记录到的各种函数调用堆栈以指定的规则进行分组,帮助你组织和找到更关心的数据。
为什么需要分组
在实际使用中,PerfView通常会收集到非常多的函数调用栈数据,包括我们关心的程序的函数调用信息,及一大堆我们不关心的其他函数调用信息,例如windows系统的底层函数。这么多有用没用的条目都列出在列表视图上,令人眼花缭乱。如何将我们不需要的数据分组归纳呢?Perfview提供分组功能。
分组功能使用类似于正则的匹配功能,将函数全名(一个函数的全名包含了程序集,命名空间,类名和函数名,例如"mscorlib.n!System.DateTime.get_Now()")进行匹配,并替换成自定义的分组名称。例如,可以对所有在Debug目录下的程序集的函数单独显示,而其他函数则分组成“OTHER”,这样,我们就可以只看见我们程序里的函数调用。其实这就是默认的[Just My App]分组规则的作用:
通配符
那么,分组功能如何使用呢?
在使用分组之前,先看看PerfView定义的几个"通配符":
* :匹配任意数量的字符
%:匹配任意数量的数字和英文字母和点号("."),等于.NET正则中的 [\w\d.]*
^ :匹配开头
|:“或”操作
{}:代表一个分组,等于.NET正则里的小括号
分组规则
PerfView中有两种分组操作,分别是 PAT->GROUP 和 PAT=>GROUP。在这里“PAT”代表需要匹配的模式(Pattern),“GROUP”代表你自定义的组名。 而这两种分组方式区别就在于中间的“->”和"=>",前者表示忽略入口函数,后者则会将入口函数显示在分组中。有时我们希望知道一个分组里的函数最初是由哪个函数开始调用的,这时候就可以使用后者了。除此之外,两种分组方式没有其他不同。
我们看看具体的分组规则的使用:
1. PAT->GROUP形式
如上述,PAT->GROUP形式是简单地将一个函数的全名称中包含"PAT"字眼的条目都分到“GROUP”组中,例如,在不分组的情况下,我们收集到的函数调用数据列表是这样的:
里面有我们Tutorial.exe的函数,例如,tutorial!Program.SpinForASecond()和tutorial!Program.RecSpin(),同时也有很多.NET的内部函数,例如 mscorlib.n!System.get_Now()和mscorlib.n!System.TimeSpan.get_TotalSeconds(),等等。假设我们只关心tutorial.exe自身的函数,而不希望被.NET内部函数所干扰,我们则可以设置一个分组规则“mscorlib->.NET”,这样,所有包含“mscorlib”字眼的方法全名称的条目都会被分组进“.NET”组,效果如下:
是不是清爽了很多?这样的分组能使我们快速地过滤掉mscorlib有关的函数,只剩下tutorial自己的函数(和一些其他函数,当然如果你愿意,也可以将其他的函数"分组"掉)
2. {*}=>$1
该形式的规则意思是: 花括号里匹配到的条目会被分组,而组名正是是花括号里的匹配到的内容,“$1”是一个占位符,对应的是花括号“{}”里的内容。假设有两个函数:tutorial!Program.SpinForASecond()和tutorial!Program.RecSpin(), 而应用的规则是“{tutorial!}->My APP $1”,则分组后,这两个函数被分进一组,并且组名为“My App tutorial!”
Perfview还支持同时设置多个规则,例如设置规则为“{tutorial!}->My APP $1;{mscorlib.ni!}->Internal $1”,这里有两个规则,一个是蓝色部分,另一个是红色部分,中间用分号(;)隔开。如果函数全名中有"tutorial!"的就分进名为“My APP tutorial!”组,而有“mscorlib.ni!”字眼的就分进“Internal mscorlib.ni!”组。
3.PAT=>GROUP
最后来看看入口点规则分组(Entry Point Grouping)。前边提到过,“PAT=>GROUP”与“PAT->GROUP”的不同在于,后者会忽略掉该组的入口函数,意味着你很难知道某个分组里的函数是从哪个函数执行进去的,而前者则会包含入口点函数信息。我们通过图例来看看实际效果。
下图中,使用“mscorlib->System Functions”规则来对mscorlib的函数进行分组,组名为“System Functions”,但除非你展开这个分组的明细,查找每个函数调用树,否则你不知道是什么函数调用了这组函数。
而现在使用“mscorlib=>System Functions”,看看有什么不同:
System Functions组明确指示了该组的函数的入口点是“mscorlib.ni!System.DateTime.get_Now()”函数,即DateTime.Now导致了这些函数的执行。
以上便是PerfView的分组功能。但其实这只是分组功能中的一部分。通过规则的搭配可以有更强大的效果。而最全面的说明其实是在PerfView自带的F1帮助文件。这里只作一个抛砖引玉的简要说明。因此如果需要了解更全面的分组技巧,可以去帮助文件里搜索相关主题。