『Erlangコード最適化メモ: JSONデコード処理(1): まず基本形』の続き。
今回は、前回実装したjson_decode_1.erlを、HiPEコンパイラを使ってコンパイルした場合の結果を書いておく。
HiPE
High Performance Erlangの略。
HiPEコンパイラを使うと、Erlangのソースコードを(VMのコードではなく)ネイティブコードにコンパイルしてくれるらしい。
経験的には、バイナリ処理が中心のモジュールやデータ構造(ex. ハッシュツリー)を実装した場合、HiPEコンパイラでコンパイルするとだいたい3~4割程度高速化する印象がある。
HiPEコンパイラを使うには、コンパイル時に以下のようなオプションを指定すれば良い。
$ erl
Erlang R16B03-1 (erts-5.10.4) [source] [64-bit] [smp:2:2] [async-threads:10] [hipe]
Eshell V5.10.4 (abort with ^G)
%% nativeをコンパイルオプションに、指定するとHiPEコンパイラが使われる
> c(hoge, [native]).
{ok, hoge}.
%% hipe:help/0 でヘルプが表示できる
> hipe:help().
The HiPE Compiler (Version 3.10.2.2)
The normal way to native-compile Erlang code using HiPE is to
include `native' in the Erlang compiler options, as in:
1> c(my_module, [native]).
Options to the HiPE compiler must then be passed as follows:
1> c(my_module, [native,{hipe,Options}]).
Use `help_options()' for details.
Utility functions:
help()
Prints this message.
help_options()
Prints a description of options recognized by the
HiPE compiler.
help_option(Option)
Prints a description of that option.
help_debug_options()
Prints a description of debug options.
version() ->
Returns the HiPE version as a string'.
For HiPE developers only:
Use `help_hiper()' for information about HiPE's low-level interface
ok
%% 最適化レベルが選べたりもする (o3が最高, デフォルトはo2)
> c(hoge, [native, {hipe, [o3]}]).
{ok, hoge}.
計時
以下の表は、前回の計時結果に、HiPEコンパイラを使った場合の処理時間を追加したもの。
平均処理時間 | 1x.json | 3x.json | 9x.json | 27x.json | 81x.json | 243x.json |
---|---|---|---|---|---|---|
json_decode_1:decode/1 | 49μs | 153μs | 412μs | 1163μs | 4089μs | 11780μs |
json_decode_1:decode/1(hipe) | 24μs | 68μs | 236μs | 750μs | 2158μs | 6221μs |
json_decode_1.erlの場合は、HiPEの効果が大きく、nativeオプションを指定しただけで、処理時間が半分程度になっている。
ただしHiPEコンパイラを使うと、エラー補足時のスタックトレースから、エラーが発生した関数の引数の情報や行番号が消えてしまうようで、デバッグが一気に難しくなるのが困りもの。(R16B03時点)
%% HiPE無しでコンパイルした場合
> json_decode_1:decode(<<"[1,2,]">>). % 不正なJSONを渡す
** exception error: bad argument
in function json_decode_1:value/1
called as json_decode_1:value(<<"]">>) % 引数情報がつく
in call from json_decode_1:array/2 (json_decode_1.erl, line 44) % 行番号もつく
in call from json_decode_1:decode/1 (json_decode_1.erl, line 18)
%% HiPE有りでコンパイルした場合
> json_decode_1:decode(<<"[1,2,]">>).
** exception error: bad argument
in function json_decode_1_hipe:value/1 % 関数名のみ
in call from json_decode_1_hipe:array/2
in call from json_decode_1_hipe:decode/1
in call from lists:reverse/1 % 何故か経由していないはずの関数が含まれている
ソースコードの修正は一切行っていないが、今回はここまで。
とりあえずJSONデコードのケースでは、HiPEが結構有効なことが分かった。
補足
計測環境:
- CPU: Intel(R) Core(TM) i7-4600U CPU @ 2.10GHz (VMware上で二コア)
- OS: Scientific Linux release 6.5 (Carbon)
- Erlang: R16B03-1 (erts-5.10.4)