Erlang Thursday - timer:tc/3

今天的Erlang Thursday要讲的函数是 timer:tc/3.

我相信我们所有人写测量目标代码执行耗时的代码都是先获取当前时间,接着执行目标代码,再获取当前时间,最后将前后两个时间的差作为目标代码的执行耗时。在Erlang里,按这种方式来写的话将像下面这样:

1
2
3
4
5
6
7
8
Time1 = now().
% {1420,519186,111375}
timer:sleep(4000). % Do something
% ok
Time2 = now().
% {1420,519190,118280}
timer:now_diff(Time2, Time1).
% 4006905

我们可以注意到这么一个现象:因为now()函数返回一个元组格式的时间戳,所以我们不能将两个元组相减来得到时间差,就像我们在其他语言里能够将两个时间相减;因此我们必需使用 timer:now_diff/2

作为一个好的“工程师”,我们知道因为我们必需在应用的不同地方做一些事情,那么我们可以在一个地方创建我们自己的函数让这个函数去做这些事情。

难过的是(意思是我们不需要这么做了):聪明的Erlang语言团队已经为我们做了这个事情并且以timer:tc/3这个函数的方式提供给我们用。

timer:tc/3接收模块名,函数名以及一个参数列表作为入参。因为我们通常要得到我们调用的函数的结果,另外还有时长,这个结果就是一个元组,其中第一个元素是时长,它的单位是微妙,另一个元素是传给timer:tc/3的第二个参数(它是一个函数)的执行结果。例子如下:

1
2
3
4
timer:tc(timer, sleep, [4000]).
% {4003097,ok}
timer:tc(lists, foldl, [fun(X, Accum) -> X + Accum end, 0, lists:seq(1, 2000000)]).
% {5099481,2000001000000}

另外还有timer:tc/1,它仅接收一个函数并执行它;还有timer:tc/2,它接收一个函数和一个入参列表,然后执行它。例子如下:

1
2
3
4
timer:tc(fun() -> lists:foldl(fun(X, Accum) -> X + Accum end, 0, lists:seq(1, 2000000)) end).
% {5709293,2000001000000}
timer:tc(fun lists:foldl/3, [fun(X, Accum) -> X + Accum end, 0, lists:seq(1, 2000000)]).
% {5766480,2000001000000}

原文链接: https://www.proctor-it.com/erlang-thursday-timer-tc-3/