Memory Mapped File
Memory mapped file は仮想メモリのしくみをつかったファイルアクセスの方法です。
現代的な OS では仮想アドレス空間と物理アドレス空間を分離することで、実メモリよりもおおきなアドレス空間をあつかうことができます。ページングをつかった仮想メモリシステムでは図1のように仮想アドレス空間と物理アドレス空間をページ単位にわけて、仮想アドレス空間上で必要になったページのみを物理アドレス空間に割り当てることで効率よくメモリを利用します。
Memory mapped file ではこの仕組みをつかってプロセスの仮想アドレス空間にファイルをマッピングします。read(2)
による固定長のバッファをつかった細切れのアクセスにくらべ、簡単に連続したメモリとしてアクセスできるようになります。仮想メモリの仕組みにより必要になったときに物理アドレス空間に (ページ単位で) 読み込まれるので自動的に遅延読み込みをおこなうことができます2。
書き込み時は copy-on-write が適用され、書き込みのないページは物理アドレス空間上でプロセス間共有されます。
データ構造をバイナリイメージのまま利用する
Sudachi では辞書ファイルの読み込みにこの memory mapped file の仕組みを利用しています。Java 版では MappedByteBuffer、Sudachi.rs/SudachiPy では memmap2 を通じて辞書ファイルを直接メモリ上にマッピングします。これによって比較的おおきな辞書ファイルを効率よく読み込むことができ、またプロセス間で共有することでメモリ消費をおさえることができます。
一方で、ファイルイメージを直接メモリ上にマッピングしてしまうため、通常ファイル読み込み時におこなうような読み込みながらバイナリデータをオブジェクトに変換していくことができなくなります。
そこで Sudachi 辞書では TRIE や連接表などは int や short の配列だけでデータ構造をつくり、バイナリイメージのまま利用できるようにしています。またオブジェクトの作成が必要な WordInfo
などはできるだけ生成を遅延し、文字列も Java の char 配列でダンプするようにしています。
これらのテクニックは茶筌や MeCab でつちかわれてきたものです。昨今ではこういった工夫が必要な場面もすくなくなりましたが、ときには古い技術を見直すのもいいかもしれません。
ではよい Sudachi life を。