« マルチコアでスケールしないErlangVM | Main | E-3 + 12-60SWD + FL-50R 購入 »

Friday, September 28, 2007

マルチコアでスケールしないErlang その2

というわけでスケールしないことがわかるようなテストでやり直し.

ちなみに,測定は4コアの Intel Xeon E5335 @ 2.00GHz ×2の環境で行った.
データを共有しないような処理であれば,理論上は8倍の性能となる環境である.


まず,2つずつのペアのプロセスを作り,1つのプロセスがもう1つのプロセスへ多数メッセージを送るベンチ.
プロセスを同時100ペア起動し,メッセージを100000回ずつ送信・受信する.
それぞれのペア同士でしか通信を行わないので,SMP環境であればスケールしてよさそうに思えるところだが...

> erl -noshell -eval 'mesbench:test(),halt().'
{2886904,ok}
> erl -smp -noshell -eval 'mesbench:test(),halt().'
{29280698,ok}

10倍の差がついてしまう.


もう1つ.標準で付いてくるcryptoモジュールで暗号化をやるベンチ.
同時に100プロセスを起動し,それぞれが暗号化・復号を1000回ずつ行う.
ユーザ側のコードでは,データは一切共有しない.

> erl -noshell -eval 'crypttest:test(),halt().'
{2700277,ok}
> erl -smp -noshell -eval 'crypttest:test(),halt().'
{3896708,ok}

これもやはり遅くなってしまう.

Erlangで,C言語のライブラリ(この場合はopenssl)を使う場合,リンクインドライバを使うのだが,リンクインドライバがそもそも同時に1つのプロセスからしか利用できないことが多い.
(file,inetのモジュールだけが例外で,smp対応のドライバになっている模様.)

その上,このようなドライバの実装を見ると,いったん1つのプロセスにメッセージを集めて,そのプロセスがドライバと通信するような仕組みになっているので,絶対に速度が向上しない構造になってしまっている.


まぁ,そんなわけで,やっぱりSMP環境で性能が出ない感じ.
実際のいろいろな処理を行うコードでも,-smp を使うと速度が低下してしまって,使えないことが多いのではないかと思う.

やっぱり今後のバージョンアップに期待...


測定したソースは以下の通り.

・メッセージのテスト


-module(mesbench).
-compile(export_all).

test() ->
crypto:start(),
io:format("~p~n", [timer:tc(?MODULE, bench, [100, 100000])]).

bench(Proc, Count) ->
benchspawn(Proc, Count),
benchwait(Proc * 2).

benchspawn(0, _Count) ->
ok;
benchspawn(Proc, Count) ->
Pid = spawn(?MODULE, benchchild_recv, [self(), Count]),
spawn(?MODULE, benchchild_send, [self(), Count, Pid]),
benchspawn(Proc - 1, Count).

benchwait(0) ->
ok;
benchwait(Proc) ->
receive
ok -> ok
end,
benchwait(Proc - 1).

benchchild_recv(Parent, 0) ->
Parent ! ok;
benchchild_recv(Parent, Count) ->
receive
_ -> ok
end,
benchchild_recv(Parent, Count - 1).

benchchild_send(Parent, 0, _Receiver) ->
Parent ! ok;
benchchild_send(Parent, Count, Receiver) ->
Receiver ! {message, Count},
benchchild_send(Parent, Count - 1, Receiver).

・暗号化のテスト

-module(crypttest).
-compile(export_all).


test() ->
crypto:start(),
io:format("~p~n", [timer:tc(?MODULE, bench, [100, 1000])]).

bench(Proc, Count) ->
benchspawn(Proc, Count),
benchwait(Proc).

benchspawn(0, _Count) ->
ok;
benchspawn(Proc, Count) ->
spawn(?MODULE, benchchild, [self(), Count]),
benchspawn(Proc - 1, Count).

benchwait(0) ->
ok;
benchwait(Proc) ->
receive
ok -> ok
end,
benchwait(Proc - 1).

benchchild(Parent, 0) ->
Parent ! ok;
benchchild(Parent, Count) ->
Iv = <<"12345678901234567890">>,
Enc = encrypt(Iv, <<"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890">>),
Dec = decrypt(Iv, Enc),
benchchild(Parent, Count - 1).


% 暗号化関連

get_secretekey() ->
<<"1234567890">>.

encrypt(Iv, Data) ->
encrypt(get_secretekey(), Iv, Data).

decrypt(Iv, Data) ->
decrypt(get_secretekey(), Iv, Data).

encrypt(Key, Iv, Data) ->
{BinLen, PaddedData} = padding(Data),
concat_binary([BinLen, crypto:aes_cbc_128_encrypt(erlang:md5(Key), erlang:md5(Iv), PaddedData)]).

decrypt(Key, Iv, Data) ->
<> = Data,
PaddedData = crypto:aes_cbc_128_decrypt(erlang:md5(Key), erlang:md5(Iv), RestData),
unpadding(Len, PaddedData).

padding(Data) ->
Len = iolist_size(Data),
BinLen = <>,
{BinLen, [Data, list_to_binary(lists:duplicate((16 - (Len rem 16)) rem 16, "\0"))]}.

unpadding(Len, Data) ->
<> = Data,
BinData.


|

« マルチコアでスケールしないErlangVM | Main | E-3 + 12-60SWD + FL-50R 購入 »

Comments

The comments to this entry are closed.

TrackBack


Listed below are links to weblogs that reference マルチコアでスケールしないErlang その2:

« マルチコアでスケールしないErlangVM | Main | E-3 + 12-60SWD + FL-50R 購入 »