code

2017年3月2日 星期四

Erlang筆記10 - process spawn需要的時間

測試一下spawn一個process需要的時間

先來看以下這段code:

-module(processes).-export([max/1]).

max(N) ->
  Max = erlang:system_info(process_limit),
  io:format("Maximum allowed processes:~p~n",[Max]),
  statistics(runtime),
  statistics(wall_clock),
  L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
  {_, Time1} = statistics(runtime),
  {_, Time2} = statistics(wall_clock),
  lists:foreach(fun(Pid) -> Pid ! die end, L),
  U1 = Time1 * 1000 / N,
  U2 = Time2 * 1000 / N,
  io:format("Process spawn time=~p (~p) microseconds~n",
    [U1, U2]).wait() ->
  receive    die -> void
  end.
for(N, N, F) -> [F()];
for(I, N, F) -> [F()|for(I+1, N, F)].

黃色部分是一個for function的定義,這個把N個F()的結果給放到一個 list中。
所以可以看到L是一個N個 spawned processes PIDs的list,每一個process只是單純的執行wait()。
wait to die!!!!!

然後在綠色部分做一個map的動作,這個mapping其實就是把process kill掉而已。
再來就是把這N個process spawn用system time來算出執行時間。

在我的電腦上,結果如下:
Maximum allowed processes:262144
spawnedProcess spawn time=3.1 (1.55) microseconds


增加max allowed processes

262144 = 2^18
我們試試看加大erlang emulator能乘載的processes數目:


其實就看你的電腦記憶體有多大,我開500萬個processes,因為記憶體只有16g,所以需要至少 > 10g,所以還沒開到500萬個就爆掉了。


timeout

這可以拿來寫成process waiting timeout:


或是timer:
(沒有receive 會compile不過! 所以是為什麼?)

或是做buffer flushing:


這段code的意義是 由於after 0,所以馬上就timeout return true,但是在 return 之前,會先執行一次receive clause,所以match anything之後又recursively call itself,這樣就會一直把received到的東西給讀取(但是沒做任何事),直到再也沒有_Any可以match就結束了這個process。

如果拿掉after 0 clause的話,這個process要是沒有收到東西也不會結束自己。

利用timeout時候 (i.e. after 0)會先檢查receive clause的語言特性,可以做出很多變化,非常好用!

在語言層級支援這個還蠻神奇的。



一個可以 cancel的timer

-module(mtimer).
-export([timer/2, start/2, cancel/1]).
timer(Microsecs, Func) ->
  receive    cancel ->
      void
  after Microsecs ->
    Func()
  end.
start(Microsecs, Func) ->
  spawn(fun() -> timer(Microsecs, Func) end).
cancel(Pid) ->
  Pid ! cancel.


這樣的架構就用到了after 的好處。使用如下:



沒有留言:

張貼留言