编写Erlang timeit函数

时间:2016-07-26 13:00:50

标签: erlang

我想写一个Erlang timeit函数(比如Python模块)作为一个学习练习,告诉我特定函数运行了多长时间。问题是,我在Erlang中非常棒,并且无法弄清楚如何做到这一点。

尝试1(尝试制作累加器):

timeit_acc(T, start, F) -> timeit_acc({os:timestamp(), T}, finish, F);
timeit_acc({T1, T2}, finish, F) -> element(T1, 2) - element(T2, 2).
timeit(F) -> timeit_acc(os:timestamp(), start, F).

这当然不起作用,因为我无法确定实际调用函数F的位置。我也非常确定这个代码不是唯一的问题。 :P

尝试2(尝试使函数执行多个语句,如Python):

timeit(F)->
    {M, S, MS} = os.timestamp(),
    F,
    {M2, S2, MS2} = os.timestamp(),
    {M2 - M1, S2- S1, MS2- MS1}.

我非常希望第二次尝试,但遇到了以下砖墙:

79> c(timeit).
timeit.erl:11: syntax error before: '.'
timeit.erl:3: function timeit/1 undefined
error

现在我考虑一下,我也想知道如果函数F可以有不同数量的参数,我该如何处理它。 。 。有人可以告诉我这是怎么做到的吗?当然,一点点解释会非常好。

====更新====

根据评论中收到的建议,该功能的新版本为:

timeit(F) ->
    {M, S, MS} = os:timestamp(),
    Val = F(),
    {M2, S2, MS2} = os:timestamp(),
    {{M2 - M, S2 - S, MS2 - MS}, Val}.

然而,现在我不确定如何使用它。我试图分析erlang:time/0函数但失败了:

109> c(timeit).
{ok,timeit}
110> timeit:timeit(time).
** exception error: bad function time

2 个答案:

答案 0 :(得分:3)

在尝试2中,您的函数调用看起来像os.timestamp,在模块名称和函数名称之间有一个点,就像在Python中一样,但在Erlang中应该是冒号:os:timestamp。< / p>

从Erlang 18开始,os:timestamp的替代方案是erlang:monotonic_time。如果我正确理解the documentation,“Erlang单调时间”可能是您想要用来测量函数调用期间所用时间的时间戳。

来自timer:tc source code

tc(F) ->
    T1 = erlang:monotonic_time(),
    Val = F(),
    T2 = erlang:monotonic_time(),
    Time = erlang:convert_time_unit(T2 - T1, native, micro_seconds),
    {Time, Val}.

erlang:monotonic_time()本身在未指定的“本机”时间单位中返回时间戳作为整数。这就是为什么需要调用erlang:convert_time_unit,才能从native转换为micro_seconds。您也可以在获得时间戳的位置调用erlang:monotonic_time(micro_seconds)进行转换。

答案 1 :(得分:2)

你的第二次尝试非常接近。 试试这个,

timeit(F,Args) ->
    {MS, S, US} = os:timestamp(),
    erlang:apply(F,Args),
    {MS2, S2, US2} = os:timestamp(),
    {MS2-MS,S2-S,US2-US}.

注意: https://github.com/Leonardo610/tirocinio允许您运行带有参数列表的函数。在上面的代码中,Args应该是一个包含函数F的所有参数的列表。例如,如果您想要运行具有3个参数的函数Args将是[Arg1,Arg2,Arg3]。 (这也包括零参数)。见下面的例子。

<强>示例:

3> testit:timeit(fun(X) -> X+X end, [5]).
{0,0,7}
4> testit:timeit(fun lists:append/2, [[1,2,3],[4,5,6]]).
{0,0,1}
5> testit:timeit(fun() -> io:format("Fun with no args~n",[]) end, []).
Fun with no args
{0,0,688}