我很好奇一个典型的C#分析器是如何工作的?
虚拟机中是否有特殊的挂钩?
是否可以轻松扫描函数调用的字节代码并将调用注入启动/停止计时器?
或者它真的很难,这就是为什么人们为此付费的工具?
(作为旁注,我发现有点有趣,因为它非常罕见 - 谷歌在搜索中完全错过了船只“how does a c# profiler work?”根本不起作用 - 结果是关于空调......)
答案 0 :(得分:3)
Microsoft提供免费的CLR Profiler,版本4.0。
https://www.microsoft.com/downloads/en/details.aspx?FamilyID=be2d842b-fdce-4600-8d32-a3cf74fda5e1
顺便说一句,CLR Profiler文档中有一个很好的部分,它详细介绍了它的工作原理,第103页。这里有来源作为发行版的一部分。
答案 1 :(得分:3)
扫描字节代码是否容易 函数调用和注入调用 启动/停止计时器?
或者它真的很难,这就是原因 人们为此付出了工具吗?
注入电话很难,需要工具才能完成。
不仅难度很大,而且是找到瓶颈的一种非常间接的方式。 原因在于瓶颈是你的代码中的一个或少数语句负责花费大量时间,时间可以显着减少 - 即它不是真正必要的,即它是浪费的。 如果您可以告诉其中一个例程的平均包含时间(包括IO时间),并且您可以将它乘以它被调用的次数,并除以总时间,您可以告诉例程的百分比时间需要。 如果百分比很小(如10%),你可能在其他地方遇到更大的问题。 如果百分比较大(如20%至99%),您可能会在例程中遇到瓶颈。 所以现在你必须在例程中搜索,查看它调用的内容以及他们采取的时间。你也想避免被递归(调用图的bugaboo)弄糊涂。
有适用于不同原则的分析器(例如适用于Linux,Shark和其他的Zoom)。 原则是有一个函数调用堆栈,并且在例程中负责(执行工作或等待其他例程执行它所请求的工作),它是在堆栈上。 所以,如果它负责50%的时间(比方说),那就是它在堆栈上的时间, 无论被叫多少次,或每次通话需要多少时间。 不仅是堆栈上的例程,而且花费时间的特定代码行也在堆栈上。 你不需要寻找它们。 您不需要的另一件事是测量精度。 如果您采用10,000个堆叠样本,那么有罪行将以50 +/- 0.5%进行测量。 如果你取100个样本,它们将被测量为50 +/- 5%。 如果你取10个样本,它们将被测量为50 +/- 16%。 在每种情况下你都能找到它们,这就是你的目标。 (并且递归并不重要。所有这意味着给定的行在给定的堆栈样本中可以出现多次。)
关于这个问题,有很多困惑。无论如何,对于发现瓶颈最有效的分析器是那些在挂钟时间内对堆栈进行采样并逐行报告的分析器。 (如果对某些myths about profiling进行透视,很容易看出。)
答案 2 :(得分:1)
1)没有“典型”这样的东西。人们通过各种方式收集配置文件信息:对PC进行时间采样,检查堆栈跟踪,捕获方法/语句/编译指令的执行计数,在代码中插入探针以收集计数以及可选地调用上下文以在调用上下文中获取配置文件数据基础。这些技术中的每一种都可能以不同的方式实施。
2)有分析“C#”和分析“CLR”。在MS世界中,您可以分析CLR并将CLR指令位置反向转换为C#代码。我不知道Mono是否使用相同的CLR指令集;如果他们没有,那么你不能使用MS CLR分析器;你必须使用Mono IL分析器。或者,您可以使用C#源代码来收集分析数据,然后在MS,Mono或某人的C#兼容自定义编译器上编译/运行/收集该数据,或者在WinCE等嵌入式系统中运行C#,其中空间很宝贵,像CLR-built-ins这样的功能往往会被遗忘。
监视源代码的一种方法是使用源到源转换,将代码从其初始状态映射到包含数据收集代码以及原始程序的代码。这个paper on instrumenting code to collect test coverage data显示了如何通过插入在执行代码块时设置特定于块的布尔标志的语句来使用程序转换系统来插入测试覆盖率探测器。计数分析器替换那些探测器的反递增指令。时序分析器为这些探测器插入时钟快照/增量计算。我们的C# Profiler实现了C#源代码的计数和时序分析;它还通过使用收集执行路径的更复杂的探针来收集调用图数据。因此,它可以通过这种方式在调用图上产生定时数据。这个方案适用于任何你可以获得中等分辨率时间值的地方。
答案 3 :(得分:1)
这是一篇冗长文章的链接,该文章讨论了仪器和抽样方法: