LZ4 の Erlang バインディングを(作ってもらって)使ってみた

LZ4 Extremely Fast Compression algorithm

http://code.google.com/p/lz4/

ドラクエ 10 にも使われている圧縮アルゴリズム LZ4 を Erlang から使うバインディングを試してみました。

https://github.com/joewilliams/erlang-lz4

動かしてみたところ ... セグフォ ... というカナシイ結果でした ... 。

@szktty 版

ということで仕事で Erlang の NIF ばかり書いているという噂の @szktty を言いくるめて、作ってもらいました。

https://github.com/szktty/erlang-lz4

APL2.0 で公開されています。

compress/uncompress

APIErlang ライクになっています。そもそも圧縮ライブラリなので compress/uncompress は圧縮、展開するだけです。 ただし世に出回っているバインディングは圧縮前のサイズをくっつけて圧縮後としているので気持ち悪い仕様でした。

このバインディングは展開する際は圧縮前のサイズを引数に取ります。

-type option() :: high | {block, integer()}.
-spec compress(binary()) -> {ok, binary()} | {error, term()}.
-spec compress(binary(), [option()]) -> {ok, binary()} | {error, term()}.
-spec uncompress(binary(), integer()) -> {ok, binary()} | {error, term()}.

pack/unpack

ただ、上のだけだと使いづらいと思うので、Python や node.js バインディングが使っている圧縮前の長さをくっつけた版に対応した API も用意してもらいました。

-type pack() :: binary().
-spec pack(binary()) -> {ok, pack()} | {error, term()}.
-spec pack(binary(), [option()]) -> {ok, pack()} | {error, term()}.
-spec unpack(pack()) -> {ok, binary()} | {error, term()}.

サンプル

文字列データに効果があるらしいので文字列で試してみました。

%% 文字データをまず作ります
1> Raw = <<"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.">>.

%% 1000 倍にしてみます
2> Raw1 = binary:copy(Raw, 1000).

%% 圧縮します
3> {ok, C} = lz4:pack(Raw1).
{ok,<<96,228,1,0,242,88,76,111,114,101,109,32,105,112,115,117,109,32,100,111,108,111,114,32,115,105,116,...>>}

%% 圧縮前のサイズ
4> byte_size(Raw1).
124000

%% 圧縮後のサイズ
5> byte_size(C).   
622

%% 戻します
6> {ok, U} = lz4:unpack(C).
{ok,<<"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolo"...>>}

%% 圧縮前と戻したデータが一致しました
7> Raw1 =:= U.
true

感想

かなりの効果はでるようですが、文字データじゃないバイナリデータの場合はあまり効果なさそうでした。完全なランダムバイナリでは一切効果は出ませんでした(まぁ当たり前ですが)。

それにしてもサクサク NIF を作れる @szktty さすがですね。