2009-01-20 63 views
19

当我在一个大学项目上工作时,我使用了一个由大一学生制作的项目内部分析器,它非常基本,但是它的任务是减少代码的两个点之间的时间并给出统计数据。代码分析器如何工作?

现在,专业分析器如何工作?它预处理代码插入检查点或类似的东西?它是否使用调试数据读取二进制代码以捕获函数的调用位置?

谢谢。

回答

22

有很多不同的分析器以不同的方式工作。

常用的分析器只是定期检查正在运行的程序,以查看当前正在执行的程序指令(程序计数器)和哪些例程调用当前函数(调用栈)。这种类型的采样 profiler可以使用标准二进制文件,但如果您有调试符号来计算程序中指定地址的代码行,它将更加有用。

除了定期采样,还可以使用处理器性能计数器在一定数量的事件(如缓存未命中)之后进行采样,这将帮助您查看由于内存访问而导致程序的哪些部分变慢。其他分析器涉及重新编译程序以插入指令(称为仪器)以计算每个连续指令集(基本块)被执行的频率,或者甚至可以记录执行基本块的序列,或者在某些地方记录变量的内容。

仪器方法可以为您提供所有您想要的精度和数据,但会降低程序速度并改变其性能特征。相比之下,使用基于抽样的方法,您可以根据所获得的配置文件数据的准确性,根据需要运行该程序的时间长度来调整性能影响。

2

它取决于正在分析的代码的类型,例如.NET CLR为代码分析器提供facility。在处理托管代码时,可以重写中间代码以注入自定义钩子。您也可以分析应用程序的堆栈跟踪。操作系统可以提供分析的手段,例如Windows有performance counters。处理嵌入式代码时,您可以模拟/替代底层硬件以有效监视系统性能。

+0

你是什么意思的“托管代码”? – tunnuz 2009-01-20 10:19:38

+0

http://en.wikipedia.org/wiki/Managed_code – aku 2009-01-20 10:21:50

13

有两种常见的性能分析策略(无论如何都是基于虚拟机的语言):仪器和采样。

每次方法启动和完成时,插装检查点并通知分析器。这可以通过JIT /解释器完成,也可以通过后期正常编译但预执行阶段完成,该阶段仅更改可执行文件。这可能会对性能产生非常显着的影响(从而扭曲任何时序结果)。尽管获得准确的数字很好。

采样会定期询问VM对于所有线程都是什么样的堆栈跟踪,并以此方式更新其统计信息。这通常会影响性能,但会产生较不准确的通话计数。

0

gprof in * nix,在编译和链接时使用-pg,将一些额外的代码注入到目标代码中。然后通过运行gprof,由注入的代码生成报告文件。

2

正如Jon Skeet上面写到的那样,有两种策略:仪器和采样。

仪器手动和自动完成。在手动情况下:开发人员手动插入代码来跟踪感兴趣的代码区域的开始/结束。例如一个简单的“StartTimer”和“EndTimer”。某些分析器工具也可以自动完成此操作 - 为此,分析器需要对代码执行静态分析,即分析代码并确定重要的检查点,如特定方法的开始/结束。对于支持反射的语言(例如任何.net语言),这是最容易的。使用“反射”,剖析器能够重建整个源代码树(以及调用图)。

采样由探查器完成,它会查看二进制代码。分析器还可以使用Hooks或陷阱Windows事件/消息等技术来进行性能分析。

仪器和采样方法都有自己的开销。开销的量取决于 - 例如,如果采样频率设置为较高值,则剖析本身可以对所报告的性能作出显着贡献。

仪器与采样: 它不像一个比另一个更好。两者都有自己的位置。

最好的方法是从基于采样的分析器开始,并查看整个系统级别。运行采样器并查看系统资源使用情况:内存,硬盘,网络,CPU。

从上面确定正在窒息的资源。

通过上述信息,您现在可以将代码添加到您的代码中,以查明罪魁祸首。例如,如果内存是最常用的资源,那么它将有助于检测与内存分配相关的代码。请注意,使用仪器,您真的专注于代码的特定区域。