本章描述了如何通过记录函数被调用的次数、条件语句的分支被执行的次数等来分析 OCaml 程序的执行过程。
在分析执行过程之前,必须使用 ocamlcp 作为 ocamlc 编译器的前端(参见第 13 章)或 ocamloptp 作为 ocamlopt 编译器的前端(参见第 16 章)以性能分析模式编译程序。当分别编译模块时,在编译模块(生成 .cmo 或 .cmx 文件)时必须使用 ocamlcp 或 ocamloptp,并且也可以在将它们链接在一起时使用(尽管这不是严格必需的)。
如果一个模块(.ml 文件)没有对应的接口(.mli 文件),那么使用 ocamlcp 编译它将生成与 ocamlc 生成的对象文件(.cmi 和 .cmo)不兼容的对象文件,这可能会导致问题(如果 .cmi 或 .cmo 仍然存在)在性能分析编译和非性能分析编译之间切换时。为了避免此问题,您应该始终为每个 .ml 文件提供一个 .mli 文件。 ocamloptp 也存在相同的问题。
为了确保您的程序能够以性能分析模式编译,请避免使用任何以 __ocaml_prof 开头的标识符。
可以通过 -P 选项传递给 ocamlcp 或 ocamloptp 来控制性能分析信息的量,后面跟着一个或多个字母,指示程序的哪些部分应该被分析
例如,使用 ocamlcp -P film 编译将分析函数调用、if…then…else…、循环和模式匹配。
在不带 -P 选项的情况下调用 ocamlcp 或 ocamloptp 将默认为 -P fm,这意味着仅分析函数调用和模式匹配。
为了与以前的版本兼容,ocamlcp 也接受 -p 选项,其参数和行为与 -P 相同。
ocamlcp 和 ocamloptp 命令还接受相应 ocamlc 或 ocamlopt 编译器的所有选项,除了 -pp(预处理)选项。
运行使用 ocamlcp 或 ocamloptp 编译的可执行文件将记录程序指定部分的执行计数,并将它们保存到当前目录中的名为 ocamlprof.dump 的文件中。
如果程序退出时设置了环境变量 OCAMLPROF_DUMP,则其值将用作文件名,而不是 ocamlprof.dump。
仅当程序正常终止(通过调用 exit 或直接退出)时才会写入转储文件。如果程序因未捕获的异常而终止,则不会写入它。
如果当前目录中已经存在兼容的转储文件,则性能分析信息将累积到此转储文件中。例如,这允许在不同输入上对程序的多次执行进行性能分析。请注意,由字节码可执行文件(使用 ocamlcp 编译)生成的转储文件与由原生可执行文件(使用 ocamloptp 编译)生成的转储文件兼容。
ocamlprof 命令生成程序模块的源代码列表,其中执行计数已作为注释插入。例如,
ocamlprof foo.ml
打印 foo 模块的源代码,并带有指示该模块中函数被调用次数的注释。当然,只有在编译后源文件没有被修改的情况下,此信息才是准确的。
ocamlprof 识别以下选项
使用 ocamlprof 进行的性能分析仅记录执行计数,而不记录每个函数中实际花费的时间。目前,无法对由 ocamlc 生成的字节码程序执行时间性能分析。对于原生代码的时间性能分析,建议用户使用标准工具,如 perf(在 Linux 上)、Instruments(在 macOS 上)和 DTrace。不再支持使用 gprof 进行性能分析。