ファイルシステム on ファイルシステム と ファイルシステム on DBM
ユーザーランドでP2P分散ファイルシステムを実装してFUSEでマウントするとき、バックエンドはファイルシステムの方が速いのか、DBMの方が速いのか。
ファイルシステムはファイルシステムとして使うのに適したデータ構造になっているはずなので、ファイルシステムの方が速そうな気がする。
だけどもファイルシステムはカーネルスペースで動くので、sendfile()とかでがんばらないとread/writeでカーネルスペース→ユーザースペースのコピーが発生するし、open()とかstat()とかでいちいちコンテキストスイッチが発生する。
open()したファイルディスクリプタをキャッシュするとか、余分にがんばらないといけない。分散ファイルシステム的に操作は全部ステートレスでないと困るので、「さっきopen()したファイルの〜」といった操作をプロトコルに加えることはできない。
一方DBMはユーザーランドで動くので、コンテキストスイッチは発生しない。ファイルシステムと言っても結局はパスをキーとしたマップで表せるわけで。値は [付加情報, データ]。マルチフォークとかExtended Attributesとかは気にしない方向で。
ハードリンクやらinodeやらと言った概念は、そもそも分散ファイルシステムの段階で有り得ない概念なので、別にバックエンドでサポートされていたところでどうしようもない。(どうやって全ノードでユニークな番号を割り当てろと)
と言うわけで最近見つけたTokyo Cabinet。これはピッタリな感あり。
データベース本体だけではなくて、実はユーティリティAPI群も便利なんじゃないか。
read()を非同期にできない。どうしたってディスクからのread()は非同期にできないのだけど。マルチスレッドにしない限り。…逆にwriteは普通非同期だけど。
読み込みたいデータがキャッシュに載っていることが期待できるか否かで、戦略が変わる気がする。
載っていることが期待できるなら、ブロック覚悟でread()する。
どうせ載ってないだろー&読み込むデータが十分大きいなら、別スレッド(カーネルスレッド)でread()してmutex+conditionで同期する。あるいはlightyみたいに、tmpfsにLinux AIOでコピーしてシグナルで同期する。非同期はどっちも実装がうげげになるのでヤな感じ。