C++ で書かれた、シンプル、高速で省メモリな独自形式の辞書 (変換にかかる時間は数秒です) を使用する SKK サーバです。 Linux/MacOSX/FreeBSD/OpenBSD/Cygwin で動作します。
バージョン 0.3.6 以降のライセンスは SKK と同じ GPL です。
current : yaskkserv-0.4.0.tar.bz2 (54060 bytes sha1sum:a38dfc1694c10b7040c0aa7351a2866399b81e4f) (2008年4月30日(水) 更新)
何かありましたら
へのメイルや 電言板 まで、お気軽にどうぞ。 2ch UNIX 板の「SKK専用スレッド Part7」 も見てます。
| オプション | 機能 | simple | normal | hairy |
|---|---|---|---|---|
| --check-update | 辞書の更新をチェックし自動で再読み込みします。デフォルトは disable です。 | × | ○ | ○ |
| --debug | 現在は使用していません。デフォルトは disable です。 | ○ | ○ | ○ |
| --help | ヘルプメッセージを表示し、終了します。 | ○ | ○ | ○ |
| --log-level=LEVEL | ログレベルを指定します。 0 - 9 の範囲で指定でき、数値が大きいほど詳細なログを出力します。ログは syslog に出力されます。デフォルトは 1 です。 | ○ | ○ | ○ |
| --max-connection=N | 最大同時接続数を指定します。デフォルトは 8 です。 | ○ | ○ | ○ |
| --port=PORT | ポートを指定します。デフォルトは 1178 です。 | ○ | ○ | ○ |
| --server-completion-midasi-length=LENGTH | completion で返す見出しの最大数を指定します。この数を越えると completion は失敗します。デフォルトは 0.3.5_SKK_ML_TEST_20070814_0 より前の版では 1024 、以降は 2048 です。あまり大きな値を指定する意味はない (補完候補は事実上 100 程度を越えた時点意味がなくなるのでは?) ので、デフォルトを小さな値にし失敗時に特定のメッセージを返すか、指定数までは返すような実装にすべきかもしれません。 | × | × | ○ |
| --server-completion-midasi-string-size=LENGTH | completion で生成される文字列バッファを LENGTH バイト用意します。生成される文字列がこのサイズを越えると completion は失敗します。デフォルトは 0.3.5_SKK_ML_TEST_20070814_0 より前の版では 131072 、 以降は 262144 です。 | × | × | ○ |
| --server-completion-test=type | SKK ML 「server completion の仕様の欠陥」で提案された 1 - 4 案を指定します。デフォルトは 1 です。 | × | × | ○ |
| --version | サーバのバージョンを表示し、終了します。 | ○ | ○ | ○ |
yaskkserv では以下のような実装になっています。
| type | サーバの実装 |
|---|---|
| 1 | 変更なし。 |
| 2 | / を含む見出しを含めない。 |
| 3 | スペース区切りにする。 |
| 4 | プロトコル c を追加しスペース区切りにする。プロトコル 4 は / のまま。 |
gcc3.3 系 + メモリが少ない環境で、コンパイラのバグを踏むためコンパイルできないという問題が確認されています。作者の環境ではメモリが 256M の機械でバグを踏みます。 512M の機械では問題ありません。この問題はオプティマイズレベルが高いと発生するようです。
yaskkserv-0.3.3 以降では configure でコンパイラバグを踏みそうな環境を検知し、自動的にオプティマイズレベルを下げます。
yaskkserv-0.3.3 より前のバージョンでは
といった対処をする必要があります。
わざわざ書きおこしたのは
といった理由からです。
用途によって、いくつかのサーバを用意しています。
以下のような特徴があります。
使用した辞書は 2005年10月12日(水) あたりの SKK-JISYO.total+zipcode です。(482220 エントリ 15930937 bytes)
「最小サイズ」はインデックスデータとブロックリードバッファを同じ領域に置くことでメモリを節約した場合のサイズです。(この場合は当然、インデックスデータを毎回ストレージから RAM へ読み込む必要があります。)
現在の実装ではインデックスデータとブロックリードバッファを別に確保するので、「合計サイズ」だけメモリを消費します。
「--short-block」は辞書サイズを大きくすることでインデックスデータを小さくする形式です。
| オプション | ブロックリードバッファサイズ | インデックスデータサイズ | 合計サイズ | 最小サイズ |
|---|---|---|---|---|
| --block-size=4096 | 4k | 58k | 62k | 58k |
| --block-size=8192 | 8k | 32k | 36k | 32k |
| --block-size=16384 | 16k | 18k | 36k | 18k |
| --block-size=4096 --alignment --short-block | 4k | 36k | 40k | 36k |
| --block-size=8192 --alignment --short-block | 8k | 20k | 28k | 20k |
| --block-size=16384 --alignment --short-block | 16k | 11k | 27k | 16k |
SKK-JISYO.total+zipcode (482220 エントリ 15930937 bytes) をコンバートした場合のサイズです。
| オプション | サイズ | 比率 |
|---|---|---|
| --block-size=4096 | 14152648 | 88.8% |
| --block-size=8192 | 14125252 | 88.6% |
| --block-size=16384 | 14111500 | 88.5% |
| --block-size=4096 --alignment | 14656456 | 91.9% |
| --block-size=8192 --alignment | 15104196 | 94.8% |
| --block-size=16384 --alignment | 15926028 | 99.9% |
| --block-size=4096 --alignment --short-block | 14635072 | 91.8% |
| --block-size=8192 --alignment --short-block | 15093156 | 94.7% |
| --block-size=16384 --alignment --short-block | 15920200 | 99.9% |
文字列がひらがなまたは ASCII だけで構成されていれば下位バイトのみ使用し、それ以外の文字が存在する場合は先頭に \x1 を追加するエンコード形式です。
ex.) ああああ → \xa2\xa2\xa2\xa2 (下位バイトのみ) ひらがな漢字 → \x1ひらがな漢字 (先頭に \x1) LIFEFORCE → LIFEFORCE (ASCII のみ) ぐらでぃうす2 → \xb0\xe9\xc7\xa3\xa6\xb9\x32 (下位バイト + ASCII) 沙羅曼蛇 → \x1沙羅曼蛇 (先頭に \x1)
見出しやインデックスデータ中の文字列でこのエンコード形式を採用しています。
インデックスデータは一般に RAM 上へ置かれます。ここでストレージ上にある辞書の読み込むべきブロックが確定するため、ストレージへのアクセスは 1 度の探索あたり必ず 1 回以下 (運が良ければキャッシングされ 0 回) になります。
インデックスデータをストレージに置いておき、ブロックリードバッファと同じ領域に読み込んでから使うこともできます。この場合メモリは節約できますが、ストレージへのアクセスが 1 度の探索あたり必ず 2 回 (インデックスデータの読み込み + 辞書のブロック読み込み) になります。
インデックスデータは以下の要素から構成されます。 (詳しくはソースコード skk_jisyo.hpp のコメントをごらんください。)
struct FixedArray は「通常エントリ」の探索に使用します。「ひらがなエンコード」された先頭 1 バイトが添字となります。「特殊エントリ」は struct FixedArray を参照せず、直接ブロックを探索します。
struct FixedArray には struct Block の開始インデックス、長さとブロック終端文字列へのオフセットが含まれています。ここで指定されたどこかのブロックに探索文字列は存在することになります。どのブロックに含まれるかは、ブロック終端文字列と探索文字列を比較することで判定します。
文字列を比較して
+---------+ 「探索文字列」が「終端文字列」以下ならば
|Block N-1| そのブロックに存在
+----------+ index=N +---------+ 探索文字列が "あい" ならば Block N+1 に存在
|FixedArray|--+-------->|Block N |
+----------+ | ^ +---------+---"ああああ" Block N の 終端文字列
| | |Block N+1|
| len=4 +---------+---"あいいいいい" Block N+1 の 終端文字列
| | |Block N+2|
| v +---------+---"あかかかか" Block N+2 の 終端文字列
+-------> |Block N+3|
+---------+---"あさささ" Block N+3 の 終端文字列
|Block N+4|
特殊エントリ開始 +---------+
ブロック -------------> |Block N+5|
index = N+5 +---------+
|Block N+6|
+---------+
struct Block の個数と文字列格納領域は 2005年10月12日(水) あたりの SKK-JISYO.total+zipcode の値です。
| ブロックサイズ | struct Block の個数 (通常エントリ + 特殊エントリ) | 文字列格納領域 (通常エントリ + 特殊エントリ) |
|---|---|---|
| 4k | 3563 + 1 個 | 27644 + 4 bytes |
| 8k | 1839 + 1 個 | 14043 + 4 bytes |
| 16k | 970 + 1 個 | 7241 + 4 bytes |
ブロックサイズが大きいとインデックスデータサイズは小さくなりますが、ブロックの読み込みに時間がかかり、ブロックリードバッファ内での探索時間が少し増えます。
ブロックサイズが小さいとインデックスデータサイズは大きくなりますが、ブロックの読み込み時間とブロックリードバッファ内での探索時間は減ります。しかし同一の struct FixedArray に含まれる struct Block が増え、ここでの探索時間が少し増えます。
yaskkserv は以下の環境で動作確認しています。
| OS | CPU | compiler |
|---|---|---|
| MacOSX(x86) | Core Duo | i686-apple-darwin8-g++-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5363) |
| gentoo linux(amd64) | Athlon64 X2 3800+ | g++ (GCC) 4.1.1 (Gentoo 4.1.1-r3) |
| gentoo linux(amd64) | Athlon64 3200+ | g++ (GCC) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10) |
| gentoo linux(x86) | C3 | g++ (GCC) 4.1.1 (Gentoo 4.1.1-r3) |
| FreeBSD(VMware freebsd-6.2-i386.zip) | - | g++ (GCC) 3.4.6 [FreeBSD] 20060305 |
| OpenBSD(VMware OAMP.zip) | - | g++ (GCC) 3.3.5 (propolice) |
| Cygwin | Pentium4 | g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) |
コマンド yaskkserv_make_dictionary の実行にかかる時間を time で適当に計測してみました。
使用した辞書は 2005年10月12日(水) あたりの SKK-JISYO.total+zipcode です。(482220 エントリ 15930937 bytes)
| CPU | メモリ | OS | 変換にかかった時間 |
|---|---|---|---|
| P3-600 | 320M | gentoo linux | 4-6 sec. |
| C3 1000 | 256M | gentoo linux | 3-5 sec. |
| C3 1000 | 512M | gentoo linux | 3-5 sec. |
| Athlon64 X2 3800+ | 2G | gentoo linux(amd64) | 1 sec. 程度 |
サーバへコネクションを切断するよう要求します。
「見出し」 eee に対する「変換文字列」を要求します。 " " (スペース)でターミネートされていることに注意が必要です。
サーバから返される「変換文字列」は / で区切られた "1/foo/bar/baz/\n" のような形式です。
サーバから返される文字列の末尾には "\n" が必要なことに注意が必要です。
「見出し」が存在しない場合は入力の先頭の "1" を "4" に変換したものをそのまま返します。 (実はプロトコル的には 4 で始まる文字列ならば何でも良いらしいですが、一部のクライアントで問題が出るとのことです。)
サーバへ「バージョンナンバー」を要求します。
サーバから返される「バージョンナンバー」は "A.B " のような形式です。 " " (スペース)でターミネートされていることに注意が必要です。
skkserv/skkserv.c に A はメジャーバージョン B はマイナーバージョンのような記述がありますが、 skkserv 自体 "A.B.C " のような形式で返していますし、他のサーバではサーバ文字列を返しているものもあるので、バージョンナンバーというよりバージョン情報と表現すべきなのかもしれません。
サーバへ「サーバのホスト名と IP アドレスのリスト」を要求します。
サーバから返される「サーバのホスト名と IP アドレスのリスト」は "hostname:addr:[addr...:] " のような形式です。 " " (スペース)でターミネートされていることに注意が必要です。
yaskkserv では未実装です。(ダミー文字列が返されます。)
「見出し」 eee で始まる見出しを要求します。" " (スペース)でターミネートされていることに注意が必要です。
サーバから返される「見出し」は / で区切られた "1/foo/bar/baz/\n" のような形式です。
サーバから返される文字列の末尾には "\n" が必要なことに注意が必要です。
これは新しいプロトコルで、今のところきちんとした定義は無いようです。
あいまいな点としては
といったものが挙げられます。
yaskkserv では
といった実装になっています。
skkserv/skkserv.c ではデバッグモード時にエラーメッセージをコンソールへ出力するだけのようです。
yaskkserv-0.3.0 以降では "0\n" を返します。 yaskkserv-0.3.0 より前は何も返しません。
SKK に関するメモ
| 情報 | ソース |
|---|---|
| 見出しサイズは 510 バイト | skkserv/README |
| プロトコル | skkserv/skkserv.c 、 regex-skkserv の MEMO と SKK専用スレッド Part7 の 74 さん |