第 21 章 性能分析 (ocamlprof)

本章描述了如何通过记录函数被调用的次数、条件语句的分支被执行的次数等来分析 OCaml 程序的执行过程。

1 编译以进行性能分析

在分析执行过程之前,必须使用 ocamlcp 作为 ocamlc 编译器的前端(参见第 13 章)或 ocamloptp 作为 ocamlopt 编译器的前端(参见第 16 章)以性能分析模式编译程序。当分别编译模块时,在编译模块(生成 .cmo.cmx 文件)时必须使用 ocamlcpocamloptp,并且也可以在将它们链接在一起时使用(尽管这不是严格必需的)。

注意

如果一个模块(.ml 文件)没有对应的接口(.mli 文件),那么使用 ocamlcp 编译它将生成与 ocamlc 生成的对象文件(.cmi.cmo)不兼容的对象文件,这可能会导致问题(如果 .cmi.cmo 仍然存在)在性能分析编译和非性能分析编译之间切换时。为了避免此问题,您应该始终为每个 .ml 文件提供一个 .mli 文件。 ocamloptp 也存在相同的问题。

注意

为了确保您的程序能够以性能分析模式编译,请避免使用任何以 __ocaml_prof 开头的标识符。

可以通过 -P 选项传递给 ocamlcpocamloptp 来控制性能分析信息的量,后面跟着一个或多个字母,指示程序的哪些部分应该被分析

a
所有选项
f
函数调用:在每个函数体的开头设置一个计数点
i
if …then …else …:在 then 分支和 else 分支中都设置计数点
l
while, for 循环:在循环体的开头设置一个计数点
m
match 分支:在每个分支体开头设置一个计数点
t
try …with … 分支:在每个分支体开头设置一个计数点

例如,使用 ocamlcp -P film 编译将分析函数调用、if…then…else…、循环和模式匹配。

在不带 -P 选项的情况下调用 ocamlcpocamloptp 将默认为 -P fm,这意味着仅分析函数调用和模式匹配。

注意

为了与以前的版本兼容,ocamlcp 也接受 -p 选项,其参数和行为与 -P 相同。

ocamlcpocamloptp 命令还接受相应 ocamlcocamlopt 编译器的所有选项,除了 -pp(预处理)选项。

2 分析执行过程

运行使用 ocamlcpocamloptp 编译的可执行文件将记录程序指定部分的执行计数,并将它们保存到当前目录中的名为 ocamlprof.dump 的文件中。

如果程序退出时设置了环境变量 OCAMLPROF_DUMP,则其值将用作文件名,而不是 ocamlprof.dump

仅当程序正常终止(通过调用 exit 或直接退出)时才会写入转储文件。如果程序因未捕获的异常而终止,则不会写入它。

如果当前目录中已经存在兼容的转储文件,则性能分析信息将累积到此转储文件中。例如,这允许在不同输入上对程序的多次执行进行性能分析。请注意,由字节码可执行文件(使用 ocamlcp 编译)生成的转储文件与由原生可执行文件(使用 ocamloptp 编译)生成的转储文件兼容。

3 打印性能分析信息

ocamlprof 命令生成程序模块的源代码列表,其中执行计数已作为注释插入。例如,

        ocamlprof foo.ml

打印 foo 模块的源代码,并带有指示该模块中函数被调用次数的注释。当然,只有在编译后源文件没有被修改的情况下,此信息才是准确的。

ocamlprof 识别以下选项

-args 文件名
文件名 中读取其他以换行符结尾的命令行参数。
-args0 文件名
文件名 中读取其他以空字符结尾的命令行参数。
-f 转储文件
指定要读取的性能分析信息的备用转储文件。
-F 字符串
指定要与性能分析信息一起输出的其他字符串。默认情况下,ocamlprof 将使用 (* n *) 形式的注释来注释程序,其中 n 是性能分析点的计数器值。使用 -F s 选项,注释将为 (* sn *)
-impl 文件名
处理 文件名 作为实现文件,即使其扩展名不是 .ml
-intf 文件名
处理 文件名 作为接口文件,即使其扩展名不是 .mli
-version
打印版本字符串并退出。
-vnum
打印简短的版本号并退出。
-help--help
显示简短的使用摘要并退出。

4 时间性能分析

使用 ocamlprof 进行的性能分析仅记录执行计数,而不记录每个函数中实际花费的时间。目前,无法对由 ocamlc 生成的字节码程序执行时间性能分析。对于原生代码的时间性能分析,建议用户使用标准工具,如 perf(在 Linux 上)、Instruments(在 macOS 上)和 DTrace。不再支持使用 gprof 进行性能分析。