代码分析器如何工作?
当我在做一个大学项目时,我使用了一位高年级学生制作的项目内部分析器,它非常基本但足够好,因为它的任务是减去代码两点之间的时间并提供统计数据。
现在,专业分析员是如何工作的? 它是否预处理代码以插入检查点或类似的东西? 它是否读取带有调试数据的二进制代码以捕获调用函数的位置?
谢谢。
While I was working on an University project, I used a project-internal profiler made by an elder student, it was very basic but good enough since its task was to subtract times between two points of the code and to give statistics.
Now, how does a professional profiler work? Does it preprocess the code to insert checkpoints or stuff like that? Does it read the binary code with debug data to catch where a function is called?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
有许多不同的分析器,它们以不同的方式工作。
常用的分析器只是定期检查正在运行的程序,以查看当前正在执行哪些汇编指令(程序计数器)以及哪些例程调用了当前函数(调用堆栈)。 这种采样分析器可以使用标准二进制文件,但如果您有调试符号来计算程序中给定地址的代码行,则更有用。
除了定期采样之外,您还可以使用处理器性能计数器在一定数量的事件(例如缓存未命中)后进行采样,这将帮助您了解程序的哪些部分由于内存访问而变慢。
其他分析器涉及重新编译程序以插入指令(称为检测)来计算每个连续指令集(基本块)的执行频率,或者甚至可能记录基本块的执行顺序,或者在某些地方记录变量的内容。
仪器方法可以为您提供所需的所有精度和数据,但会减慢程序速度并改变其性能特征。 相比之下,使用基于采样的方法,您可以根据运行程序所需的时间长度以及获得的配置文件数据的准确性来调整性能影响。
There are lots of different profilers which work in different ways.
Commonly used profilers simply examine the running program regularly to see what assembly instruction is currently being executed (the program counter) and which routines called the current function (the call stack). This kind of sampling profiler can work with standard binaries, but are more useful if you have debugging symbols to work out lines of code given addresses in the program.
As well as sampling regularly, you can also use processor performance counters to sample after a certain number of events such as cache misses, which will help you see which parts of your program are slowing down due to memory accesses.
Other profilers involve recompiling the program to insert instructions (known as instrumentation) to count how often each continuous set of instructions (basic blocks) are executed, or maybe even record the sequence in which basic blocks are executed, or record the content of variables at certain places.
The instrumentation approach can give you all the precision and data you might want, but will slow down the program and that will change its performance characteristics. By contrast, with sampling based approaches you can tune the performance impact against the length of time you need to run the program against the accuracy of the profile data you obtain.
有两种常见的分析策略(无论如何对于基于 VM 的语言):检测和采样。
每次方法启动和完成时,Instrumentation 都会插入检查点并通知分析器。 这可以通过 JIT/解释器或通过正常编译后但预执行阶段来完成,该阶段仅更改可执行文件。 这会对性能产生非常显着的影响(从而扭曲任何计时结果)。 不过,这对于获得准确的计数很有好处。
采样会定期向虚拟机询问所有线程的堆栈跟踪情况,并以这种方式更新其统计信息。 这通常对性能影响较小,但产生的调用计数不太准确。
There are two common profiling strategies (for VM-based languages anyway): instrumentation and sampling.
Instrumentation inserts checkpoints and informs the profiler every time a method starts and finished. This can be done by the JIT/interpreter or by a post-normal-compile but pre-execution phase which just changes the executable. This can have a very significant effect on the performance (thus skewing any timing results). It's good for getting accurate counts though.
Sampling asks the VM periodically what the stack trace looks like for all threads, and updates its statistics that way. This typically affects performance less, but produces less accurate call counts.
正如 Jon Skeet 上面所写,有两种策略:检测和采样。
仪器仪表既可以手动完成,也可以自动完成。 在手动情况下:开发人员手动插入代码来跟踪感兴趣的代码区域的开始/结束。 例如一个简单的“StartTimer”和“EndTimer”。 一些分析器工具也可以自动执行此操作 - 为此,分析器需要对代码进行静态分析,即解析代码并识别重要的检查点,例如特定方法的开始/结束。 对于支持反射的语言(例如任何.net 语言)来说,这是最容易的。 使用“反射”,探查器能够重建整个源代码树(以及调用图)。
采样由探查器完成,并查看二进制代码。 分析器还可以使用 Hooks 等技术或捕获 Windows 事件/消息来进行分析。
仪器和采样方法都有各自的开销。 开销的大小取决于 - 例如,如果采样频率设置为高值,则分析本身可以对报告的性能做出重大贡献。
仪器与采样:
这并不是说一种方法比另一种方法更好。 两者都有自己的位置。
最好的方法是从基于采样的分析器开始,然后查看整个系统级别。 即运行采样器并查看系统范围的资源使用情况:内存、硬盘、网络、CPU。
从上面确定被阻塞的资源。
有了上述信息,您现在可以将检测添加到代码中以查明罪魁祸首。 例如,如果内存是最常用的资源,那么它将有助于检测与内存分配相关的代码。 请注意,通过检测,您实际上可以专注于代码的特定区域。
As Jon Skeet wrote above there are two strategies: instrumentation and sampling.
Instrumentation is done both manually and also automatically. In manual case: the developer manually inserts code to track the start/end of a region of code of interest. For example a simple "StartTimer" and "EndTimer". Some profiler tools can do this automatically also - for this the profiler will need to do a static analysis of the code i.e. it parses out the code and identify important checkpoints like the start/end of a particular method(s). This is most easy with languages that support reflection (e.g. any .net language). Using 'reflection' the profiler is able to rebuild the entire source code tree (along with call graphs).
Sampling is done by the profiler and it looks into the binary code. The profiler can also techniques like Hooks or trap Windows events/ messages for the purpose of profiling.
Both Instrumentation and sampling methods have their own overheads. The amount of overhead depends - e.g. if the sampling frequency is set to high values, then the profiling itself can contribute significantly to the performance being reported.
Instrumentation Vs Sampling:
It is not like one is better than the other approach. Both have their place.
The best approach is to start with a sampling based profiler and look at the whole system level. That is run the sampler and see the system wide resource usage: memory, hard disk, network, CPU.
From the above identify the resources that are getting choked.
With the above info, you can now add instrumentation to your code to pin-point the culprit. For example if memory is the most used resource then it will help to instrument your memory allocation related code. Note that with instrumentation you are really concentrating on a particular area of your code.
这取决于所分析的代码类型,例如 .NET CLR 提供功能 用于代码分析器。 处理托管代码时,可以重写中间代码以注入自定义挂钩。 您还可以分析应用程序的堆栈跟踪。 操作系统可以提供分析方法,例如 Windows 具有 性能计数器。 在处理嵌入式代码时,您可以模拟/替换底层硬件以有效监控系统性能。
It depends on type of code being analyzed, for example .NET CLR provides facility for code profilers. When dealing with managed code it is possible to rewrite intermediate code to inject custom hooks. Also you can analyze stack trace of the applications. Operating system can provide means for profiling, for example Windows has performance counters. When dealing with embedded code you can emulate/substitute underlying hardware to effectively monitor system performance.
对于 *nix 中的 gprof,在编译和链接时使用 -pg,一些额外的代码被注入到目标代码中。 然后通过运行 gprof,注入的代码会生成一个报告文件。
for gprof in *nix, at compile and link time by using the -pg, some extra code is injected into the object code. Then by running gprof, a report file is generated by the injected code.