ptexenc/文字コード判定 †
ptexenc ライブラリ(ダウンロード )の PTEX_IN_FILTER + nkf コマンドを用いた、ソースの文字コードの自動判定機能は、なかなか普及しないので、対策を考えてみました。
文字コード自動判定は、pTeX の UTF-8 対応に並ぶ、重要な機能だと認識しているので、なかなか普及しないことは残念に思っています。
問題点 †
- 自分の環境は SJIS で統一されているから必要性を感じない by 大多数
- 速度低下が激しいので常用したくない by TeXnician
- nkf コマンドは用途が一般的すぎて TeX に必要なものとは思えないので TeX Live 2010 には含めない by TeX Live 開発者
1. は度外視します(爆)。
2. は PTEX_IN_FILTER だけの問題というよりは TeX の実装にも問題があります。
詳しくは後ほど説明しますが、意外なところに原因がありますし、根が深いです。
3. ですが、日本人にしか必要のない nkf コマンドを TeX Live に含めたくないという気持ちはよくわかります。そこに、日本人にとってどれだけ重要かを力説して取り込んでもらうのか、それとも穏便な別の方法を考えるのかは、よく作戦を練るべきところでしょう。
ptexenc-1.1.0 までの実装 †
C言語の fopen() でファイルを読み込むところを、フィルタプログラムを経由して読み込むように改造しました。
つまり、fopen() を popen() に置き換え、環境変数 PTEX_IN_FILTER に登録されたプログラムを起動して、その出力を読み取ります。
単純な改造の割には効果が大きく、いいアイデアだと思っていましたし、XeTeX にも似たような機能があるので、国際的にも正しい進歩をしていると思っています。
なお、ここに至るまでの経緯は ptetexWiki:UTF-8対応(3)、(5)、(6) も参考になります。
速度低下について †
さて 2. の速度低下についてです。
nkf プロセスの生成や文字コード判定に時間がかかっていると想像するのが人の常でしょうが、それは半分は間違いです。
確かにプロセス生成 (fork) のコストは無視できません。しかし、それに輪をかけて問題なのが、今の TeX + WEB(2C) では、ファイルの存在チェックだけに fopen()/fclose() してくれることです。
つまり、fopen() しても、1文字も読み取らずに fclose() することが多々あります。
ですから、fopen() を単純に popen() に置き換えると、ファイルの存在チェックのたびに nkf のプロセスを生成してしまって、大きく速度低下していまいます。
これが PTEX_IN_FILTER の実装の問題点です。
解決策 †
そこで、次のような方法を実装しました。
この実装は、しばらく ptexlive(ダウンロード )の新しいものに紛れ込ませて公開してみます。落ち着いたら ptexenc の新バージョンに独立させます。
- nkf をフィルタとして呼び出すのではなく、ptexenc ライブラリに内蔵しました。
- ファイルを open しても、まだ文字コード判定を行いません。そのまま close されれば一切余分な計算時間はかかりません。
- 文字を読み込む段階になって、その直前に初めて文字コード判定を行います。
PTEX_IN_FILTER と較べたメリットは次のようになります。
- PTEX_IN_FILTER のような速度低下がありません。
- 外部コマンドを呼び出さないので、セキュリティが向上します。
- TeX Live には、nkf コマンドが TeX に依存しない一般的なツールだという理由で、取り込んでもらえてませんが、ptexenc の一部となることで、外国の人には気付かれないように(迷惑もかけないように)取り込んでもらえます。
- UTF-8 <=> JIS のテーブルが iconv を使わずとも nkf 由来のものが手に入ります。TeX Live では好都合です。
逆に、デメリットもあります。
- PTEX_IN_FILTER のようなフィルタ処理との相性は悪く、共存のためには複雑な処理を実現せねばなりません。
- 文字コード判定の性能が nkf に固定されてしまいます。nkf 自体の普及度は高く、信頼性もあるとは思いますが、だからと言って pTeX に唯一の判定ルーチンとしてふさわしいと主張する根拠は見つかりません。もっとも、ふさわしくない理由も思いつきませんし、PTEX_IN_FILTER での使用実績もあるので、最有力であることは間違いありません。
簡単なベンチマークの結果です。Vine Linux 5.2, Core Solo U1300(1.06GHz)での実行時間(秒)です。速度低下がかなり防げていることがわかります。
| 手動 | nkf内蔵(今回) | PTEX_IN_FILTER |
---|
jsclasses.dtx | 1.18 | 1.25 | 1.50 |
---|
\input{5行}x1000回 | 0.76 | 0.79 | 12.0 |
---|
\input{50行}x1000回 | 1.59 | 1.84 | 13.4 |
---|
ご相談 †
- pTeX が(実質的に)nkf に依存してしまってよいでしょうか。ptexenc に nkf を取り込むので、アスキーさんに許可をいただく必要まではないと考えています。
- PTEX_IN_FILTER は廃止してもよいでしょうか。元々 Unix 版にしかなかったので、それほど影響は大きくはないと思います。もっとも、フィルタ機能は XeTeX にも別実装があるくらいに有力なものですが、その道を閉ざすことにもなるので、慎重に考えるべきだと思っています。
- ありがとうございます。少し modify したものでテストさせていただきました。 \input{5行}x1000回で、性能が悪い計算機なのですが、約 1.15 倍しか時間がかからなくて、劇的に改善されています。元々 W32TeX では input に対するフィルタ機能は disabled にしていました。最近コード判別だけ nkf でするようにしていましたが、やはり ファイル全体に対するフィルタ機能は disabled のままでした。 性能はやはり場合によって10倍以上の時間を要していました。そのような事情で、W32TeXでは新しい ptexenc を使用させていただきたいと思います。よろしくお願いいたします。 -- kakuto
- 早速のテストありがとうございます。パッチの実装はあまり良くないので、すぐに差し替えます。ベンチマークに用いたサンプルを添付しておきます。 -- 土村