パスワードを忘れた? アカウント作成
449897 journal

dsegの日記: Perlの日本語文字コード変換、最速は?

日記 by dseg

ふと思い立って、日本語文字コード変換処理のペンチマークを取ってみた。
対象は青空文庫から取ってきた、夏目漱石の『我輩は猫である』のテキストファイル(文字コードはSJIS)。

  • SJISからEUC、
  • SJISからUTF-8

の変換を実行してみる。

変換に使用したモジュールは

の5つ。
NKFは、/usr/bin/nkf利用ではなくて、Perlの拡張モジュールの方を指す。
jcode.pl は UTF-8への変換が出来ないので、後者のテストからは省いた。
# Text::Iconvは最新版の1.4では処理が無限ループに…。
# 何故かは判らないが、1.3ではきちんと動いた。

テストについて、
冒頭のZipファイルをダウンロード、解凍するとneko.txt(731kb)が出来る。
同じ場所に下のスクリプトを保存。

スクリプトをjp_bench.plと名前を変えて、走らせてみた結果はこうなった。

dseg@mantra ~/devel/perl$ ./jp_bench.pl
Version of Jcode = 0.87
Version of NKF = 2.04
Version of Encode = 2.08
Version of Encode::JP = 2.01
Version of Text::Iconv = 1.3
Version of jcode.pl = 2.13

Benchmark: timing 10 iterations of A_ConvertUsingJcode__, B_ConvertUsingJcodePL, C_ConvertUsingNKF____, D_ConvertUsingEncode_, E_ConvertUsingIconv__...
A_ConvertUsingJcode__: 50 wallclock secs (47.98 usr + 0.43 sys = 48.41 CPU) @ 0.21/s (n=10)
B_ConvertUsingJcodePL: 36 wallclock secs (35.58 usr + 0.22 sys = 35.80 CPU) @ 0.28/s (n=10)
C_ConvertUsingNKF____: 13 wallclock secs (13.10 usr + 0.04 sys = 13.14 CPU) @ 0.76/s (n=10)
D_ConvertUsingEncode_: 5 wallclock secs ( 4.56 usr + 0.16 sys = 4.72 CPU) @ 2.12/s (n=10)
E_ConvertUsingIconv__: 9 wallclock secs ( 8.44 usr + 0.13 sys = 8.57 CPU) @ 1.17/s (n=10)

Benchmark: timing 10 iterations of A_ConvertUsingJcode_, C_ConvertUsingNKF___, D_ConvertUsingEncode, E_ConvertUsingIconv_...
A_ConvertUsingJcode_: 49 wallclock secs (48.62 usr + 0.24 sys = 48.86 CPU) @ 0.20/s (n=10)
C_ConvertUsingNKF___: 14 wallclock secs (14.30 usr + 0.10 sys = 14.40 CPU) @ 0.69/s (n=10)
D_ConvertUsingEncode: 2 wallclock secs ( 1.96 usr + 0.17 sys = 2.13 CPU) @ 4.69/s (n=10)
E_ConvertUsingIconv_: 2 wallclock secs ( 1.42 usr + 0.13 sys = 1.55 CPU) @ 6.45/s (n=10)

結果は妥当だけど、ピュアPerlなjcode.plの健闘は意外だった。Jcodeよりも速いし。
# テストマシンのCPUはVIA C3 600MHz。かなり遅い。

結局、速度的に見ると、普通にPerl5.8.0以上の標準モジュールであるEncodeを使うのが良さそうだった。
EncodeはPerl5.8.0以上が必要だけど、
最近はプロバイダでも、提供するperlのバージョンがデフォルトで5.8.0以上のところが増えてきているように思う。

--

#!/usr/bin/perl
use strict;

use Jcode ();
use NKF ();
use Encode::JP ();
use Text::Iconv ();
require 'jcode.pl';

use Benchmark;
use vars qw/$iconv $txt $o1 $o2 $o3 $o4 $o5/;

# -----

# Check the version number of modules
print "Version of $_ = ", eval "\$${_}::VERSION", "\n"
    for qw/Jcode NKF Encode Encode::JP Text::Iconv/;
print 'Version of jcode.pl = ', $jcode::version, "\n\n";

my $file = './neko.txt';
open F, $file or die "!$\n";
read F, $txt, -s $file;

# Convert to EUC-JP
Text::Iconv->raise_error(1);
$iconv = Text::Iconv->new('Shift_JIS', 'EUC-JP');
timethese(
    10,
    {
        A_ConvertUsingJcode__ => q[ $o1 = $txt; Jcode::convert(\$o1, 'euc', 'sjis'); $o1 = undef ],
        B_ConvertUsingJcodePL => q[ $o2 = jcode::euc($txt, 'sjis'); $o2 = undef ],
        C_ConvertUsingNKF____ => q[ $o3 = NKF::nkf('-e', $txt); $o3 = undef ],
        D_ConvertUsingEncode_ => q[ $o4 = $txt; Encode::from_to($o4, 'shiftjis', 'euc-jp');$o4 = undef ],
        E_ConvertUsingIconv__ => q[ $o5 = $iconv->convert($txt); $o5 = undef ],
    });

print "\n"x3;

# Convert to UTF-8
$iconv = undef;
$iconv = Text::Iconv->new('Shift_JIS', 'UTF-8');

timethese(
    10,
    {
        A_ConvertUsingJcode_ => q[ $o1 = $txt; Jcode::convert(\$o1, 'utf8', 'sjis'); $o1 = undef ],
# B_ConvertUsingJcodePL=> q[ $o2 = jcode::euc($txt, 'sjis'); $o2 = undef ],
        C_ConvertUsingNKF___ => q[ $o3 = NKF::nkf('-w', $txt); $o3 = undef ],
        D_ConvertUsingEncode => q[ $o4 = $txt; Encode::from_to($o4, 'shiftjis', 'utf8');$o4 = undef ],
        E_ConvertUsingIconv_ => q[ $o5 = $iconv->convert($txt); $o5 = undef ],
    });

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

最初のバージョンは常に打ち捨てられる。

読み込み中...