Erlang 测量进程执行时间和reduction


Erlang的进程调度不是使用时间片的分配, 而是给每个进程或Port分配一个reduction budget, 默认值是2000. 每个操作都会花费reduction, 一旦reduction budget用完,该进程就会释放CPU,然后被重新调度,再次分配到CPU的时候又分配了2000 reduction budget,  循环往复.


#问题一, 如何测量一个进程消费了多少reduction呢 ?

答案是使用函数process_info(Pid, reductions),  下面用一个例子用来说明如何获取一个进程花费的reduction.


11> Pid = spawn(fun()->receive First->first end, receive Second->second end, receive Over->ok end end).  %%创建一个进程,该进程接收三次消息后结束.
<0.73.0>
12> process_info(Pid, reductions).                                                                    
{reductions,17}                                                                                                                                                                     %%到receive First位置挂起, 一共花费17 个reduction 
13> process_info(Pid, reductions).
{reductions,17}                                                                                                                                                                     %%此时进程被挂起, reduction 不会发生变化
14>                                                                                                   
14> 
14> Pid!first.                                                                                        
first
15> process_info(Pid, reductions).
{reductions,38}                                                                                                                                                                     %%到receive Second位置挂起, 一共花费38 个reduction 
16> process_info(Pid, reductions).
{reductions,38}                                                                                                                                                                     %%此时进程被挂起, reduction 不会发生变化
17> 
17> 
17> Pid!second.                                                                                       
second
18> process_info(Pid, reductions).
{reductions,69}                                                                                                                                                                    %%到receive Over位置挂起, 一共花费69 个reduction 
19> process_info(Pid, reductions).
{reductions,69}                                                                                                                                                                    %%此时进程被挂起, reduction 不会发生变化
20> 
20> Pid!over.


#问题二, 如何测量一个进程运行了多长时间呢 ?

答案是使用函数timer:tc,  下面用一个例子用来说明如何获取一个进程花费的时间.

#test_tc.erl

-module(test_tc).
-compile(export_all).

start(N)->tail_fac(N).

tail_fac(N) -> tail_fac(N,1).
tail_fac(0,Acc) -> Acc;
tail_fac(N,Acc) when N > 0 -> tail_fac(N-1,N+Acc).


11> timer:tc(test_tc, start, [1]).  
{2,2}                                                                                                                                                                      %%执行start(1)花费了2微秒,  单位是百万分之一秒
12> timer:tc(test_tc, start, [10]).
{2,56}                                                                                                                                                                   %%执行start(10)花费了2微秒,  单位是百万分之一秒
13> timer:tc(test_tc, start, [100]).
{5,5051}                                                                                                                                                               %%执行start(100)花费了5微秒,  单位是百万分之一秒
14> timer:tc(test_tc, start, [1000]).
{34,500501}                                                                                                                                                        %%执行start(1000)花费了34微秒,  单位是百万分之一秒
15> timer:tc(test_tc, start, [10000]).
{351,50005001}                                                                                                                                                 %%执行start(10000)花费了351微秒,  单位是百万分之一秒
16> timer:tc(test_tc, start, [100000]).
{3790,5000050001}
17> timer:tc(test_tc, start, [1000000]).
{31207,500000500001}
18> timer:tc(test_tc, start, [10000000]).
{341392,50000005000001}
19> timer:tc(test_tc, start, [100000000]).
{2227879,5000000050000001}                                                                                                                     %执行start(100000000)花费了大约2秒


#问题三, 如何测量一个reduction是多长时间呢 ?

答案是把以上两种测量关联起来,即可计算出一个reduction大约是多少时间,具体时间应该和测试环境是有依赖关系的.

下面用一个例子用来说明,同样使用上面的测试文件test_tc.erl


23> Pid = spawn(fun()->receive Number->test_tc:start(Number) end, receive Over->ok end end).    %%收到消息(计算的数字), 开始执行start函数
<0.82.0>
24> 
24> process_info(Pid, reductions).
{reductions,17}                                                                                                                                                      %%到receive Number位置挂起, 一共花费69 个reduction 
25> process_info(Pid, reductions).
{reductions,17}
26> Pid!10.                                                                                                                                                             %%发送数字10到Pid, 触发start函数
27> process_info(Pid, reductions).
{reductions,87}                                                                                                                                                       %%到receive Over位置挂起, start函数一共花费87-17 个reduction 
28> process_info(Pid, reductions).
{reductions,87}
29> f().                                                                                    
ok
30> Pid = spawn(fun()->receive Number->test_tc:start(Number) end, receive Over->ok end end).
<0.90.0>
31> process_info(Pid, reductions).                                                          
{reductions,17}
32> process_info(Pid, reductions).                                                          
{reductions,17}
33> Pid!1000.                                                                                                                                                        %%发送数字1000到Pid, 触发start函数                                 
34> process_info(Pid, reductions).
{reductions,1077}                                                                                                                                                 %%到receive Over位置挂起, start函数一共花费1077-17 个reduction 
35> process_info(Pid, reductions).
{reductions,1077}

结合问题二里面的数据,我们可以计算出 start(1000) 花费了1060个reduction, 34微秒.  1000 reduction 大约等于34 微秒, 不同的测试环境, 数字肯定会有不同.


#测试环境》

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             2
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 45
Stepping:              7
CPU MHz:               2400.000
BogoMIPS:              4800.00
Hypervisor vendor:     VMware
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              20480K
NUMA node0 CPU(s):     0-7


##博客仅作个人记录##

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值