読者です 読者をやめる 読者になる 読者になる

かってにインパクトファクター

子育てサラリーマンが日々の雑多なことをつらつらと綴ってます。時々政治ネタ経済ネタコンピュータネタなどをはさみます。

Ruby22, JRuby90, Crystal でHashを作った時にどれくらいメモリを消費するのか調べた

最近、CrystalなるRubyに近い文法を持つコンパイラをインストールしたので、いろいろと試しているのですが、今回はハッシュのベンチマーク結果です。

前回は、配列のメモリ使用量などを調べてみました。
Ruby22, JRuby90, Crystal で配列を作った時にどれくらいメモリを消費するのか調べた - かってにインパクトファクター

今回のソースもシンプルに、

a = {}

ARGV[0].to_i.times{|i|
  a[ (0..10).map{('A' .. 'Z').to_a[ (25 * rand()).to_i ]}.join ] = 1
}

また、CrystalはRubyと似ていると言っても、まだ進化している最中ということで、若干手をいれる必要が有ります。

a = Hash(String, Int32).new

ARGV[0].to_i.times{|i|
  a[ (0..10).map{('A' .. 'Z').to_a[ (25 * rand()).to_i ]}.join ] = 1
}

RubyとCrystalの現時点での違いはハッシュの宣言部分となります。Rubyでは細かいことは気にせずとりあえずHashの枠だけ作っておけば良いという感じなのですが、Crystalではどのような型の変数を入れるのか予め定義する必要があります。

今回も前回と同様、jrubyの結果も含めてみました。

実行方法は、

#Crystalをインタプリタ的に使用する場合
/usr/bin/time -f "%Us %M KB" crystal run memtest_hash.cr -- 1000
#Crystalを用いてコンパイルした場合
/usr/bin/time -f "%Us %M KB" ./memtest_hash.cr 1000
#Ruby22、Jruby90の場合。ただし、事前にrbenv localでRubyのバージョンは変更済み
/usr/bin/time -f "%Us %M KB" ruby memtest_hash 1000

という感じに、GNU Timeを用いてメモリの使用量などを計測しています。


では早速、まずはCPU時間の結果を。
f:id:postmaster:20150708002840p:plain
jrubyは起動するだけでCPU時間を使いますが、Hashを増やしていった場合の時間の増え方はCrystalと同程度。ruby22はリニアに時間が増加していきます。
Crystalでは、インタプリタ的にRunする場合とオプションなしのBuildが同じくらいで、--releaseオプションをつけるとCPU時間は若干低くなる傾向がありました。

お次はメモリ。
f:id:postmaster:20150708005214p:plain
CrystalのRunは、jrubyと同じように、最小限でも比較的メモリを多く使うようです(と言ってもjrubyほどではありませんが)。ある程度Hashが大きくなってくると、Crystalでコンパイルしたバイナリと同じように増えていきました。
ruby22は相変わらずリニアに増えていきました。
jruby90もリニアに増えてはいるんですが、増分はruby22ほどではなく、Crystalより若干大きいかな程度でした。


Ruby22の比較結果になりますが、Arrayと比べると、CPU時間にそれほど差はないんですが、メモリは4割ほど多く使っているという結果になるんでしょうか。

実はHashについては、ruby22はCrystalとくらべてもっとメモリを使っていて、Arrayのベンチ結果とくらべても大きく差がつくのではないかと思っていただけに、ちょっと意外な結果となりました。