• 締切済み

Jcodeのtrが遅いので代替のプログラムを作りたい

検索用のプログラムをつくってるのですが 検索のために全角⇒半角変換(ANK文字のみ)、ひらがな⇒カタカナ変換をしているのですが とても遅くて困ってます。 本当はCでモジュールを作りたい気がするほどのものなのですが 汎用性を考慮して、何もモジュールを使わない、または Encode モジュールだけで インデックスを作成しないという前提で高速化を実現する方法はあるでしょうか? 参考までに 合計500kバイトの114の文書ファイルを検索するのに Athlon64 3200+ (メモリ4G) で約1.5秒かかります。 本番環境には、約100M以上の5000ファイルがあるので心配です。 use Jcode; sub test { my($parm)=@_; my $zen='!”#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_‘abcdefghijklmnopqrstuvwxyz{|}'; my $han='!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}'; my $zentrs="あいうえおかきくけこがぎぐげごさしすせそざじずぜろたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよゃゅょャュョっッらりるれろわをん"; my $zentre="アイウエオカキクケコガギグゲゴサシスセソザジズゼロタチツテトダヂヅデドナニヌネノハヒフヘホバビブベボパピプペポマミムメモヤユヨヤユヨヤユヨツツラリルレロワヲン"; return Jcode->new($parm)->tr($zen,$han)->tr($zentrs,$zentre); } 参考までに、Jcode.pm v1.99(β)では、tr/(from)/(to)/ で実現されているようですが これをパクってもうまくいきませんでした。

みんなの回答

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.3

うーんと、どんなコードなのかは想像が付きませんが、例えばEUCのファイルを開き、変換処理を施して出力、というコードは次のようになります。 use encoding "euc-jp"; # コードはEUCで書く my $file = 'euc.txt'; open my $fh, '<:encoding(euc-jp)', $file; my $buffer = join undef, <$fh>; close $fh; $buffer =~ tr {!”#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_‘abcdefghijklmnopqrstuvwxyz{|}あいうえおかきくけこがぎぐげごさしすせそざじずぜろたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよゃゅょャュョっッらりるれろわをん} {!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz\{|\}アイウエオカキクケコガギグゲゴサシスセソザジズゼロタチツテトダヂヅデドナニヌネノハヒフヘホバビブベボパピプペポマミムメモヤユヨヤユヨヤユヨツツラリルレロワヲン}; # 長いですが、変換対象を全て繋げただけです。書き方の問題は後回しで。 print $buffer; exit; ただ、PerlIOレイヤーを使って処理をすると言う事は、その部分で時間はかかりますね。最も速そうなのは、レイヤーを使わずオクテット列のまま変換を加えてしまうパターンかと思いますが、それはそれで(可読性の面で…上のが高いとは思わないが)問題がありそうではあります。 蛇足ですが、検索時に逐次開いて変換するのはさすがにやめたほうが良いでしょう。変換だけでなく、ファイルIOも油断できませんので。予め変換しておき、それをインデックスファイルとして一つに保存するとか、いっそRDBにつっこんでおくとかしたほうが良さそうですね。(多分、その辺は考えてらっしゃるのだと思うので、本当に蛇足なのですが。)

ymda
質問者

お礼

結局、必要なEUCコードを(とりあえず)HEXで記述して 大体3倍速程度までにはしてみました。 さすがに、RDBをするほどではないと思います。 ・・・だとすれば、perlのソースにバイナリで埋め込むのが一番はやいかもしれません。

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.2

文字コードがすべてeuc-jpならば、 use utf8; ではなく use encoding "euc-jp"; です。 この辺は、5.8以前とは違ってリテラル等をオクテット列としては扱わなくなるので、ちょっとコツがいります。

ymda
質問者

補足

use encoding "euc-jp"; でも化けてしまいます。 現在使っているのは、eucを16進展開してるものです。 (スクリプトのせようとしたのですが、OKwebがServer error になるようで。。。)

  • hikomin
  • ベストアンサー率63% (40/63)
回答No.1

私はベンチマークを取っていないのですが、Perl 5.8でのマルチバイト環境ではどうですか?(逆質問?) use utf8; my $buffer = 'テスト用の文字列'; $buffer =~ tr/0-9A-Za-z/0-9A-Za-z/; #全角英数->半角英数 とか以下略で。いちいちJcodeインスタンスを作るとかよりはマシな気がしますが。 これで速くならないのであれば…うーん…。

ymda
質問者

お礼

うーん、お礼欄ですみません。 パクろうと思ったはずのJcode.pm v1.99 を test::Jcodeに変更して テストしてみたら、こっちのが8倍遅かったようです。汗 うーん、なぜだろう。汗 http://openlab.jp/Jcode/index-j.html

ymda
質問者

補足

速くなる前に、Webページ全体が文字化けしてしまいます。TT 内部コード、HTML出力すべてeuc-jpを使用しています。 呼び出し元:(これでヒットさせたい) use Search qw(Search); if (Search("モジレツ", "もじ")) { ヒット; } モジュール: sub Search { my($text,$keyword)=@_; $text=&test($text); $keyword=&test($keyword); return($text =~ /\Q$keyword\E/i); }

関連するQ&A