| <=新記事2009/11/12 PC版日記に短縮URLへの連携リンクを追加 =>古記事2009/11/10 最速一括検索::ブログ一括検索の対象にmixi, gree, モバゲー,手書きブログを追加して日本中の日記を網羅
1. 2009/11/11 「Perl > 文字コード > jocode.pl, Jcode.pm, Encode.pmのパフォーマンス比較/一番速いのはどれ?」 [この書込みのみ表示(記事URL紹介用) / 編集 / 削除 / トラバ送信 / 共有分類に追加(タグ付け)]拍手:1個1. Perlの文字コード変換モジュールのパフォーマンス比較をしてみようと思ったきっかけ 2. 比較テスト結果 3. パフォーマンス比較テスト結果からの結論 4. 各モジュールのパフォーマンス比較プログラム
1. Perlの文字コード変換モジュールのパフォーマンス比較をしてみようと思ったきっかけ
ちょっと貧弱な環境でやってみたら、Jcodeの呼び出しの処理のところでOut of memoryでプログラムが落ちてしまうということがあった。 そこで、この際Encode.pmへの乗り換えを検討したのですが、結局Out of memoryになることには変わりなかった。 しかし、ちょっとでもパフォーマンス等が改善するのならば、Encode.pmに切替えておこうと思った。
とりあえず検索してみたところ 「jcode.plが最速でした」 というかんじのレポートが検索結果の上の方に見つかり拝見させて頂いたのですが、その結論と理由に納得感が得られなかったので(書いている方も他の人ももっと処理がかかると思っている処理が速い/しかしその理由がない)、自分でパフォーマンス比較するプログラムを作ってみて検証してみることにしました。
結論から言うと、こちらでのベンチマーク結果だと、そっちの結論の「jcode.pl最強伝説」とは違い「Encodeモジュールが最強」となっています。
何故かなと思ってそっちのサイトのベンチマークプログラムを見てみましたが、そちらのプログラムではjcode.plの呼び出し方が変換しているつもりが実は変換していない為、実際には正常処理しないまま次から次の処理へと計測されていただけのようでした。 処理が異常に速いと書かれているjcode.plの型グロブの処理のところを
jcode::convert(*text, 'sjis'); print $text; |
とprintして$textの中身を確認してみるとShift_JISに変換されていないことが分かります。 これは、型グロブでの変換には
require 'jcode.pl'; my text = "...."; jcode::convert(*text, 'sjis'); |
という風にmyをグロブする変数に付けてしまうと名前空間がmainとしてつき変わり、別の名前空間(jcode)にある関数に型グロブとして上手く引き渡せない為です(myを外すと変換できる / でも綺麗じゃないからそもそもそういう風には使わない方が良い)。
もしかして本当にjcode.plが最速なのか...と期待したのでちょっと残念でもありますが、一般的に想定されるであろう妥当な結論にはなりました。 jcode系列で最新版のEncodeが最速というのはソフトの進化の仕方として正しいということで、この結果はEncode.pmを使っていく上で安心出来る結果なのではないかと思います。
2. 比較テスト結果
条件
| ループ回数 | 100回 |
| eucの入力ファイルのサイズ | 1.19MB |
| utf8の入力ファイルのサイズ | 1.65MB |
| jcode.plのバージョン | 2.13 |
| Jcodeのバージョン | 0.83 |
| Encodeのバージョン | 2.13 |
| Encode::EUCJPMSのバージョン | 0.07 |
| Encode::JP::H2Zのバージョン | 2.02 |
EUC-JP→Shift_JISの文字コード変換(携帯版への対応でよく使う変換)
| jcode.pl | 44秒 |
| Jcode | 54秒 |
| Encode | 41秒 |
全角文字を半角文字に変換(携帯版への対応でよく使う変換)
| jcode.pl | 56秒 |
| Jcode | 42秒 |
| Encode::JP::H2Z | 5秒 |
UTF8→EUC-JPへの変換(外部サイトのAPI対応でよく使う変換)
3. パフォーマンス比較テスト結果からの結論
EUC→Shift_JISに変換する処理でEncodeはJcodeの1.31倍速、jcode.plに比べると1.07倍速 UTF8→EUC-JPに変換する処理でEncodeはJcodeの1.33倍速 全角→半角に変換する処理でEncode::JP::H2ZはJcode.pmの8.4倍速、jcode.plに比べると11.2倍速
全パターンでEncode.pmが最善のパフォーマンスなので、迷わずEncode(Encode::EUCJPMS), Encode::JP::H2Zを選んで良いようです。 とりわけ全角文字を半角文字に変換する処理のパフォーマンス向上が著しいので、そこの処理に旧来のモジュールが文字コード変換なみの時間がかかっていることを考えると、携帯用に全角文字を半角にしたり、検索の為に文字コードを全角に統一したりする時に、大きなパフォーマンス向上が得られそうです。
なお、プログラムだけで処理出来るEUC-JP→Shift_JISより対応表が必要なUTF8→EUC-JPの方が7倍近く速いというのはちょっと予想外だったので、暇があったら後でどうしてそうなっちゃっているのか理由を調べてみようかなと思いました。
4. 各モジュールのパフォーマンス比較プログラム
ご自分の環境でも試してみて下さい。 使ったことがない方には文字コード操作の実例として参考になるかもしれません。
jcode.plのダウンロードはこちらから 他は su - でrootになってから perl -MCPAN -e shell と打って、そこで install $MODULE_NAME でインストール出来ます。
#!/usr/bin/perl -w =pod Script for comparing the performance of jcode.pl, Jcode and Encode Created by Hajime Kurita Distributed at http://www.accessup.org/pj/6_B4C9CDFDBFCDA4B5A4F3/4/list.html
Usage: perl bench_moji.pl $UTF8_FILE; =cut use strict; use Benchmark; use Encode::EUCJPMS; # MS拡張に対応したEUCを使えるように use Encode::JP::H2Z; use FileHandle; use Jcode; require './jcode.pl'; # jcode.plはこのスクリプトと同じディレクトリにあると想定 / このディレクトリ内でスクリプトは実行すること
my $file='/www/search/public_html/dev/j_diary.xml'; foreach my $ARGV (@ARGV){ $file=$ARGV[0]; # utf8のファイル } die "Please specify file encded in utf8" unless $file;
my $max=100; my %orig=(); if(my $fh=new FileHandle($file)){ local $/=undef; $orig{'utf8'}=<$fh>; $fh->close(); } else{ die $file." doesn't exist."; } my $jc=new Jcode(''); my %length=(); $orig{'euc'}=$jc->set($orig{'utf8'}, 'utf8')->euc(); $length{'utf8'}=length($orig{'utf8'}); $length{'euc'}=length($orig{'euc'});
my @mod=('jcode', 'Jcode', 'Encode'); my @from_to=('euc_sjis','utf8_euc'); my @todo=('conv', 'z2h');
print "Loop\t".$max."\n"; foreach my $from_to (@from_to){ if($from_to eq 'utf8_euc'){ print 'utf8 input length'."\t".$length{'utf8'}."\n"; } else{ print 'euc input length'."\t".$length{'euc'}."\n"; } }
foreach my $from_to (@from_to){ foreach my $todo (@todo){ foreach my $mod (@mod){ next if($from_to eq 'utf8_euc' && $mod eq 'jcode'); next if($from_to eq 'utf8_euc' && $todo eq 'z2h'); my $start=new Benchmark; for(my $i=0;$i<$max;$i++){ if($mod eq 'Encode'){ if($from_to eq 'utf8_euc'){ my $con=$orig{'utf8'}; if($todo eq 'conv'){ Encode::from_to($con, 'utf8', 'eucJP-ms'); } } else{ my $con=$orig{'euc'}; if($todo eq 'conv'){ Encode::JP::H2Z::z2h(\$con); } else{ Encode::from_to($con, 'eucJP-ms', 'cp932'); } } } elsif($mod eq 'jcode'){ my $con=$orig{'euc'}; if($todo eq 'conv'){ &jcode::sjis($con, 'euc'); } else{ &jcode::z2h_euc(\$con) } } else{ if($from_to eq 'utf8_euc'){ my $con=$orig{'utf8'}; if($todo eq 'conv'){ $jc->set(\$con, 'utf8')->euc(); } } else{ my $con=$orig{'euc'}; if($todo eq 'conv'){ $jc->set(\$con, 'euc')->sjis(); } else{ $jc->set(\$con, 'euc')->z2h(); } } } } my $end=new Benchmark; $from_to='euc_euc' if($todo eq 'z2h'); my $ver=''; my $show_mod=$mod; if($mod eq 'Encode'){ if($todo eq 'z2h'){ $show_mod='Encode::JP::H2Z'; $ver=qq{$Encode::JP::H2Z::VERSION}; } else{ $ver=qq{$Encode::VERSION}; } } elsif($mod eq 'jcode'){ if($jcode::rcsid=~ m!\s(\d+\.\d+)\s!){ $ver=$1; } } else{ $ver=qq{$Jcode::VERSION}; } print join("\t", $show_mod.' '.$ver, $todo, $from_to, timestr(timediff($end, $start)))."\n"; } } } |
実行結果例
Loop 100 euc input length 1193879 utf8 input length 1650264 jcode 2.13 conv euc_sjis 44 wallclock secs (43.64 usr + 0.04 sys = 43.68 CPU) Jcode 0.83 conv euc_sjis 55 wallclock secs (54.92 usr + 0.00 sys = 54.92 CPU) Encode 2.37 conv euc_sjis 42 wallclock secs (42.18 usr + 0.00 sys = 42.18 CPU) jcode 2.13 z2h euc_euc 55 wallclock secs (54.85 usr + 0.03 sys = 54.88 CPU) Jcode 0.83 z2h euc_euc 42 wallclock secs (42.30 usr + 0.00 sys = 42.30 CPU) Encode::JP::H2Z 2.02 z2h euc_euc 5 wallclock secs ( 4.58 usr + 0.00 sys = 4.58 CPU) Jcode 0.83 conv utf8_euc 8 wallclock secs ( 8.32 usr + 0.00 sys = 8.32 CPU) Encode 2.37 conv utf8_euc 6 wallclock secs ( 6.06 usr + 0.00 sys = 6.06 CPU) |
    |
");
}
// --> | Check | ");}
// -->
|---|
[他の記事も読む] <=新記事2009/11/12 PC版日記に短縮URLへの連携リンクを追加 =>古記事2009/11/10 最速一括検索::ブログ一括検索の対象にmixi, gree, モバゲー,手書きブログを追加して日本中の日記を網羅
・大分類が「Perl」の記事 ・この論客の記事全て
|