How fast can Erlang create processes?
博客分类:
erlang
ErlangDebianLinuxCacheOS
原文地址: http://www.lshift.net/blog/2006/09/10/how-fast-can-erlang-create-processes
Very fast indeed.
1> spawntest:serial_spawn(1).
3.58599e+5
That’s telling me that Erlang can create and tear down processes at a rate of roughly 350,000 Hz. The numbers change slightly - things slow down - if I’m running the test in parallel:
2> spawntest:serial_spawn(10).
3.48489e+5
3> spawntest:serial_spawn(10).
3.40288e+5
4> spawntest:serial_spawn(100).
3.35983e+5
5> spawntest:serial_spawn(100).
3.36743e+5
[Update: I forgot to mention earlier that the system seems to spend 50% CPU in user and 50% in system time. Very odd! I wonder what the Erlang runtime is doing to spend so much system time?]
Here’s the code for what I’m doing:
-module(spawntest).
-export([serial_spawn/1]).
serial_spawn(M) ->
N = 1000000,
NpM = N div M,
Start = erlang:now(),
dotimes(M, fun () -> serial_spawn(self(), NpM) end),
dotimes(M, fun () -> receive X -> X end end),
Stop = erlang:now(),
(NpM * M) / time_diff(Start, Stop).
serial_spawn(Who, 0) -> Who ! done;
serial_spawn(Who, Count) ->
spawn(fun () ->
serial_spawn(Who, Count - 1)
end).
dotimes(0, _) -> done;
dotimes(N, F) ->
F(),
dotimes(N - 1, F).
time_diff({A1,A2,A3}, {B1,B2,B3}) ->
(B1 - A1) * 1000000 + (B2 - A2) + (B3 - A3) / 1000000.0 .
This is all on an Intel Pentium 4 running at 2.8GHz, with 1MB cache, on Debian linux, with erlang_11.b.0-3_all.deb.
我的实验如下:
root@nd-desktop:~/otp_src_R13B01# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Pentium(R) Dual-Core CPU E5200 @ 2.50GHz
stepping : 6
cpu MHz : 1200.000
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm lahf_lm
bogomips : 4988.06
clflush size : 64
power management:
^Croot@nd-desktop:~# erl -smp disable
Erlang R13B01 (erts-5.7.2) [source] [rq:1] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.2 (abort with ^G)
1> os:getpid().
"14244"
2> spawntest:serial_spawn(1).
749026.6398814741
^Croot@nd-desktop:~/otp_src_R13B01# erl -pa /root
Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.2 (abort with ^G)
1> spawntest:serial_spawn(1).
402022.00990099803
结论是 beam比beam.smp要快很多,因为是所以的锁都去掉了。
我们来strace -o beam.trace.out -p 14244
root@nd-desktop:~# tail beam.trace.txt
clock_gettime(CLOCK_MONOTONIC, {3240006, 740886937}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 740914525}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 740942182}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 740970048}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 740997775}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 741025363}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 741053090}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 741080956}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 741109242}) = 0
clock_gettime(CLOCK_MONOTONIC, {3240006, 741137318}) = 0
发现大量的sys调用, user和sys的时间都很多,这是不正常的。
gdb看了下 原来是
erl_process.c:alloc_process()
{...
erts_get_emu_time(&p->started); /* 获取进程创建时间*/
...
}
昂贵的系统调用哦 去掉它。。。
重新编译再看下结果。
root@nd-desktop:~/otp_src_R13B01# bin/erl -smp disable -pa /root
Erlang R13B01 (erts-5.7.2) [source] [rq:1] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.2 (abort with ^G)
1> spawntest:serial_spawn(1).
2264041.5859158505
2>
root@nd-desktop:~/otp_src_R13B01# bin/erl -pa /root
Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.2 (abort with ^G)
1> spawntest:serial_spawn(1).
652946.9454488944
2>
看到了吧 在beam vm下每秒最多可创建 2百万个进程 比原来快了3倍, 也就是说 创建一个进程并且销毁的开心是 0.5us 太快了, 我的机器的bogo mips是4988, 哈哈 2500个指令就搞定了 快快快。。。
结论是: 系统调用对于服务器的性能是很大的杀手!!