非常教程

Erlang 20参考手册

tools

2. cprof - The Call Count Profiler

cprof 是一个分析工具,可用于了解系统中不同功能被调用的频率。

cprof使用类似于本地呼叫追踪的断点,但包含计数器,以收集分析数据。因此,不需要特殊编译要分析的任何模块。

cprof以减少的总呼叫计数顺序呈现所有分析模块,并且对于每个模块,还以降低的呼叫计数顺序呈现所有分析功能。可以指定呼叫计数限制以过滤低于限制的所有功能。

分析按以下步骤进行:

cprof:start/0..3通过在其上设置呼叫计数断点,开始使用指定功能的归零呼叫计数器进行分析。Mod:Fun()运行要分析的代码。cprof:pause/0..3暂停指定功能的呼叫计数器。这最大限度地减少了运行在后台或外壳中的干扰分析的代码的影响。呼叫计数器在主机字长度“达到上限”时自动暂停。对于32位主机,最大计数器值为2147483647. cprof:analyse/0..2收集呼叫计数器并计算结果。cprof:restart/0..3对于指定的功能,从零开始重新启动计数器。可以用来收集一组新的计数器,而不必停止并开始呼叫计数分析。cprof:stop/0..3通过从指定函数中删除调用计数断点来停止分析。

可以将函数指定为系统中的全部,全部位于一个模块中,所有模块中的一个函数,一个函数或所有尚未加载的模块中的所有函数。到目前为止,BIF不能被追踪电话号码。

分析结果可以是所有模块,也可以是一个模块。在任何一种情况下,都可以给出一个呼叫计数限制,以在呼叫计数低于限制的情况下过滤功能。所有模块的分析并没有包含该模块cprof本身,它只能通过指定它作为一个单一模块,用于分析进行分析。

与其他形式的跟踪相比,呼叫计数跟踪非常​​轻便,因为不需要生成跟踪消息。一些测量表明在10%附近的性能下降。

以下部分显示了使用分析的一些示例cprof。另见cprof(3)

2.1例:背景工作

从Erlang shell:

1> cprof:start(), cprof:pause(). % Stop counters just after start
3476
2> cprof:analyse().
{30,
 [{erl_eval,11,
            [{{erl_eval,expr,3},3},
             {{erl_eval,'-merge_bindings/2-fun-0-',2},2},
             {{erl_eval,expand_module_name,2},1},
             {{erl_eval,merge_bindings,2},1},
             {{erl_eval,binding,2},1},
             {{erl_eval,expr_list,5},1},
             {{erl_eval,expr_list,3},1},
             {{erl_eval,exprs,4},1}]},
  {orddict,8,
           [{{orddict,find,2},6},
            {{orddict,dict_to_list,1},1},
            {{orddict,to_list,1},1}]},
  {packages,7,[{{packages,is_segmented_1,1},6},
               {{packages,is_segmented,1},1}]},
  {lists,4,[{{lists,foldl,3},3},{{lists,reverse,1},1}]}]}
3> cprof:analyse(cprof).
{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
4> cprof:stop().
3476

这个例子展示了shell为了解释第一个命令行而执行的后台工作。大部分工作都是由erl_eval和完成的orddict

本例中捕获的内容是shell在解释实际调用to cprof:start()和之间发生的命令行时所执行的部分工作cprof:analyse()

2.2示例:一个模块

从Erlang shell:

1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
1
2> cprof:analyse(calendar).
{calendar,9,
          [{{calendar,df,2},1},
           {{calendar,dm,1},1},
           {{calendar,dy,1},1},
           {{calendar,last_day_of_the_month1,2},1},
           {{calendar,last_day_of_the_month,2},1},
           {{calendar,is_leap_year1,1},1},
           {{calendar,is_leap_year,1},1},
           {{calendar,day_of_the_week,3},1},
           {{calendar,date_to_gregorian_days,3},1}]}
3> cprof:stop().
3271

这个例子告诉我们“Aktiebolaget LM Ericsson&Co”是星期一注册的(因为第一个命令的返回值是1),并且calendar模块需要9个函数调用来计算它。

使用cprof:analyse()在此示例中,还显示了与第一个示例中大致相同的背景工作。

2.3示例:在代码中

编写一个模块:

-module(sort).
      
-export([do/1]).
      
do(N) ->
    cprof:stop(),
    cprof:start(),
    do(N, []).
      
do(0, L) ->
    R = lists:sort(L),
    cprof:pause(),
    R;
do(N, L) ->
    do(N-1, [random:uniform(256)-1 | L]).

从Erlang shell:

1> c(sort).
{ok,sort}
2> l(random).
{module,random}
3> sort:do(1000).
[0,0,1,1,1,1,1,1,2,2,2,3,3,3,3,3,4,4,4,5,5,5,5,6,6,6,6,6,6|...]
4> cprof:analyse().
{9050,
 [{lists_sort,6047,
              [{{lists_sort,merge3_2,6},923},
               {{lists_sort,merge3_1,6},879},
               {{lists_sort,split_2,5},661},
               {{lists_sort,rmerge3_1,6},580},
               {{lists_sort,rmerge3_2,6},543},
               {{lists_sort,merge3_12_3,6},531},
               {{lists_sort,merge3_21_3,6},383},
               {{lists_sort,split_2_1,6},338},
               {{lists_sort,rmerge3_21_3,6},299},
               {{lists_sort,rmerge3_12_3,6},205},
               {{lists_sort,rmerge2_2,4},180},
               {{lists_sort,rmerge2_1,4},171},
               {{lists_sort,merge2_1,4},127},
               {{lists_sort,merge2_2,4},121},
               {{lists_sort,mergel,2},79},
               {{lists_sort,rmergel,2},27}]},
  {random,2001,
          [{{random,uniform,1},1000},
           {{random,uniform,0},1000},
           {{random,seed0,0},1}]},
  {sort,1001,[{{sort,do,2},1001}]},
  {lists,1,[{{lists,sort,1},1}]}]}
5> cprof:stop().
5369

这个例子显示了一些lists:sort/1工作原理的细节。它在模块中使用了6047个函数调用lists_sort来完成工作。

这一次,由于shell没有涉及,因此在分析过程中没有其他工作在系统中完成。如果您尝试使用新启动的Erlang模拟器重试相同的示例,但省略了该命令l(random),则分析将显示更多由code_server其他人完成的自动加载模块的函数调用random

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1