11.分析 | 11. Profiling

11剖面图

11.1不要猜测性能配置文件

即使是经验丰富的软件开发人员也常常对其程序中的性能瓶颈进行错误的猜测。因此,请对程序进行分析,查看性能瓶颈所在,并集中精力优化它们。

Erlang/OTP包含了几个帮助查找瓶颈的工具:

  • fprof提供关于程序时间花费在哪里的最详细信息,但它会显著减慢它所描述的程序。

  • eprof提供程序中使用的每个函数的时间信息。没有生成调用图,但是eprof对它所描述的程序的影响要小得多。

如果程序太大,无法被分析fprofeprofcovercprof工具可用于定位代码部件,这些代码部件将使用以下方法进行更彻底的分析。fprofeprof...

  • cover提供每一行进程的执行计数,其开销小于fprof可以使用执行计数来查找潜在的性能瓶颈,但要注意一些。

  • cprof是最轻量级的工具,但它只为所有进程提供基于函数%28的执行计数,而不是为每个进程%29提供执行计数。

这些工具将在Tools...

11.2大系统

对于大型系统,首先在模拟和有限的场景上运行分析可能很有趣。但是,只有当许多事情同时发生,并且涉及到许多节点时,瓶颈才会出现或导致问题。因此,在实际目标系统上的系统测试设备中运行Profile也是可取的。

对于大型系统,您不希望在整个系统上运行分析工具。相反,您希望集中精力于中央流程和模块,它们对执行的很大一部分贡献很大。

11.3寻找什么

在分析分析活动的结果文件时,查找多次调用并具有长“自有”执行时间%28次(不包括对其他函数的调用)%29的函数。被多次调用的函数也可能很有趣,因为如果经常重复,即使是小的事情也可以加起来相当多。另外,问问自己,你能做些什么来减少这一次。以下是适合自己提问的问题类型:

  • 是否有可能减少调用函数的次数?

  • 如果测试的顺序被更改,是否可以减少任何测试的运行频率?

  • 是否可以删除任何多余的测试?

  • 计算出的表达式是否每次都给出相同的结果?

  • 还有其他方法可以做到这一点,并且更有效吗?

  • 是否可以使用另一个内部数据表示来提高效率?

这些问题并非总是琐碎的回答。可能需要一些基准来支持你的理论,并避免在你的理论错误的情况下使事情变慢。有关详细信息,请参阅Benchmarking...

11.4件工具

fprof

fprof度量每个函数的执行时间,包括自己的时间,即一个函数用于其自身执行的时间,以及累积的时间,即包括被调用的函数。每个进程都显示这些值。您还可以了解每个函数被调用了多少次。

fprof是基于跟踪到文件,以尽量减少运行时性能的影响。使用fprof只是调用几个库函数,请参阅fprof工具中的手册页。fprof在R8中被引入。

埃普罗

eprof是基于Erlangtrace_infoBIF。eprof显示每个进程使用了多少时间,以及在哪个函数调用中花费了这个时间。时间表示为总时间和绝对时间的百分比。有关更多信息,请参见eprof工具中的手册页。

盖盖

主要用途cover是覆盖分析,以验证测试用例,确保涵盖所有相关代码。cover在每个模块的基础上,计算程序运行时每一行可执行代码的执行次数。

显然,可以使用这些信息来确定哪些代码非常频繁地运行,因此可以作为优化的主题。使用cover只是调用几个库函数,请参阅cover工具中的手册页。

cprof

cprof是介于fprofcover关于特征。它根据每个模块计算程序运行时调用每个函数的次数。cprof具有较低的性能退化效果%28与fprof%29,并且不需要将任何模块重新编译为配置文件%28。cover29%。有关更多信息,请参见cprof工具中的手册页。

工具摘要

ToolResultsSize of ResultEffects on Program Execution TimeRecords Number of CallsRecords Execution TimeRecords Called byRecords Garbage Collection
fprofPer process to screen/fileLargeSignificant slowdownYesTotal and ownYesYes
eprofPer process/function to screen/fileMediumSmall slowdownYesOnly totalNoNo
coverPer module to screen/fileSmallModerate slowdownYes, per lineNoNoNo
cprofPer module to callerSmallSmall slowdownYesNoNoNo

11.5标杆

基准测试的主要目的是找出一个给定算法或函数的哪个实现最快。标杆远非一门精确的科学。今天,%27s操作系统通常运行很难关闭的后台任务。缓存和多个CPU核并不能方便基准测试。在进行基准测试时,最好是以单用户模式运行UNIX计算机,但至少对于临时测试来说,这是不方便的。

基准测试可以测量挂钟时间或CPU时间.

  • timer:tc/3测量挂钟时间。挂钟时间的优点是在测量中包括I/O、交换和操作系统内核中的其他活动。缺点是测量值差别很大。通常情况下,最好运行几次基准,并注意最短的时间,这是在最佳情况下可能达到的最小时间。

  • statistics/1有论点runtime测量用于Erlang虚拟机的CPU时间。CPU时间的优点是从运行到运行的结果更加一致。缺点是操作系统内核%28中所花费的时间(如交换和I/O%29)不包括在内。因此,如果涉及任何I/O%28文件或套接字%29,则测量CPU时间会产生误导。

这可能是一个好主意,同时做墙壁-时钟测量和CPU时间测量。

一些最后的建议:

  • 这两种度量类型的粒度都可能很高。因此,确保每个单独的测量至少持续几秒钟。

  • 为了使测试公平,每个新的测试运行都是在自己的新创建的Erlang进程中运行。否则,如果所有测试都在同一个进程中运行,则后面的测试将以更大的堆大小开始,因此可能会减少垃圾收集。还可以考虑在每个测试之间重新启动Erlang模拟器。

  • 不要假设给定算法在计算机体系结构X上的最快实现也是计算机体系结构Y上最快的实现。