您的位置:首页 > 其它

Erlang 测量进程执行时间和reduction

2016-12-14 03:50 281 查看
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

##博客仅作个人记录##
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: