2006年11月1日水曜日

[Perl] Encode Jcode Unicode::Japanese のベンチマーク比較

[Perl] Encode.pm Jcode.pm のベンチマーク比較 について
Encode, Text::Iconv, Unicode::Japanese, Jcode, jcode.pl のベンチマーク比較
掘り下げて頂いたので、もう一度検証してみました。
と、言っても同じではつまらないので、半角カタカナ→全角カタカナ変換を追加してみました。

実行環境
CentOS4.4 on VMware Perl 5.8.5

対象モジュール
Encode.pm 2.01(標準で入っているもの)
Jcode.pm 0.83
Unicode::Japanese 0.38
※全て XS
※Text::Iconv は半角カナ→全角カナ変換対応してないので省きました

シナリオ
「ASCII,漢字、全角カタカナ、半角カタカナ、ひらがなの混じったtext」に対して
・euc/utf8 相互変換
・euc変換時に半角カナ→全角カナ変換

・文字コード自動判別機能を使用する(guess)
・文字コード自動判別機能を使用しない(fixed)
それぞれ実施

ソースコード
use strict;
use warnings;
use Benchmark ':all';
use Jcode;
use Encode;
use Encode::JP::H2Z;
use Encode::Guess qw(euc-jp utf-8 shiftjis 7bit-jis);
use Unicode::Japanese;

my $text = qq{ASCII,漢字、全角カタカナ、半角カタカナ、ひらがなの混じったtext};

cmpthese(
timethese(
50000,
{
'Jcode::new(guess)' => sub {
       my $text = $text_org;
# euc => utf8
$text = Jcode->new($text)->utf8;
# utf8 => euc
$text = Jcode->new($text)->h2z->euc;
},

'Jcode::new(fixed)' => sub {
       my $text = $text_org;
# euc => utf8
$text = Jcode->new($text,'euc')->utf8;
# utf8 => euc
$text = Jcode->new($text, 'utf8')->h2z->euc;
},

'Jcode::convert(guess)' => sub {
       my $text = $text_org;
# euc => utf8
Jcode::convert(\$text, 'utf8');
# utf8 => euc
Jcode::convert(\$text, 'euc');
},

'Jcode::convert(fixed)' => sub {
       my $text = $text_org;
# euc => utf8
Jcode::convert(\$text, 'utf8', 'euc');
# utf8 => euc
Jcode::convert(\$text, 'euc', 'utf8', "z");
},

'Encode(guess)' => sub {
       my $text = $text_org;
# euc => utf8
Encode::from_to($text, 'Guess', 'utf8');
# utf8 => euc
Encode::from_to($text, 'Guess', 'euc-jp');
Encode::JP::H2Z::h2z(\$text);
},

'Encode(fixed)' => sub {
       my $text = $text_org;
# euc => utf8
Encode::from_to($text, 'euc-jp', 'utf8');
# utf8 => euc
Encode::from_to($text, 'utf-8', 'euc-jp');
Encode::JP::H2Z::h2z(\$text);
},

'Unicode::Japanese::new(guess)' => sub {
       my $text = $text_org;
# euc => utf8
$text = Unicode::Japanese->new($text, 'auto')->utf8;
# utf8 => euc
$text = Unicode::Japanese->new($text, 'auto')->h2z->euc;
},

'Unicode::Japanese(fixed)' => sub {
       my $text = $text_org;
# euc => utf8
$text = Unicode::Japanese->new($text, 'euc')->utf8;
# utf8 => euc
$text = Unicode::Japanese->new($text, 'utf8')->h2z->euc;
},
}
)
);

結果
・文字コード自動判別を使用しない(fixed)
Encode(fixed): 3 wallclock secs ( 2.40 usr + 0.00 sys = 2.40 CPU) @ 20833.33/s (n=50000)
Jcode::convert(fixed): 4 wallclock secs ( 3.78 usr + 0.00 sys = 3.78 CPU) @ 13227.51/s (n=50000)
Jcode::new(fixed): 4 wallclock secs ( 4.30 usr + 0.01 sys = 4.31 CPU) @ 11600.93/s (n=50000)
Unicode::Japanese::new(fixed): 25 wallclock secs (24.88 usr + 0.05 sys = 24.93 CPU) @ 2005.62/s (n=50000)

 Encode がTOP、僅差で Unicode::Japanese。この差は誤差と言ってもいいですね。少し開いて Jcode::convert と Jcode::new が続く。3位4位の差も誤差の範囲。

 続いて Jcode::convert と Jcode::new 。2位3位の差は誤差の範囲。ダントツでビリがUnicode::Japanese。Unicode::Japanese は、半角カナ変換を使用すると大幅に遅くなります。

・文字コード自動判別を使用する(guess)
Encode(guess): 10 wallclock secs ( 9.34 usr + 0.01 sys = 9.35 CPU) @ 5347.59/s (n=50000)
Jcode::convert(guess): 12 wallclock secs (12.18 usr + 0.03 sys = 12.21 CPU) @ 4095.00/s (n=50000)
Jcode::new(guess): 14 wallclock secs (13.65 usr + 0.03 sys = 13.68 CPU) @ 3654.97/s (n=50000)
Unicode::Japanese::new(guess): 25 wallclock secs (25.33 usr + 0.04 sys = 25.37 CPU) @ 1970.83/s (n=50000)

 ダントツで Unicode::Japanese がTOP、自動判別なしと比べても遜色ないのが素晴らしいですね。Encode Jcode は自動判別でかなり遅くなります。

 こちらもTOPが Encode 、 続いて Jcode::convert と Jcode::new 。2位3位の差は誤差の範囲。ビリがUnicode::Japanese。Encode Jcode は自動判別でかなり遅くなってます。Unicode::Japanese は自動判別なしと差がありませんが、半角カナ変換による大幅な低下によりビリになってしまいます。

このような結果から、半角カタカナ→全角カタカナ変換を利用する場合、Encode または Unicode::Japanese が候補に挙がりますが、
・自動判別しない場合、レンタルサーバ等でコンパイル環境が無い場合は標準の Encode
・コンパイル環境があり、自動判別使う場合は Unicode::Japanese
が良さそうです。Unicode::Japanese の使い勝手の良さにも惹かれます。

再検証の結果から Perl5.8 環境では
・半角→全角カナ変換を利用する=Encode
・半角→全角カナ変換を利用しない
   〃       &自動判別しない=Encode
           &自動判別する=Unicode::Japanese
が良さそうです。

また、Unicode::Japanese が半角→全角変換を行うと大幅に遅くなりますが、
これは Encode や Jcode は「半角カナのみ全角に変換する」に対して、Unicode::Japanese は「ASCIIも含めて全ての半角文字を全角にする」といった仕様の違いが影響しているのかもしれません。

追記)
ソースコードを以下の2点修正し再検証しました。
・変換前文字列を保持するため、各メソッドに my $text = $text_org; を追加。
・Unicode::Japanese に半角→全角カナ変換を追加。

0 件のコメント: