Igo: GAE版の辞書データ読み込み速度向上
igo-gaeを修正して、辞書データ読み込みを速度を向上させた。
※ igo-gaeの現在のバージョンは0.0.2。
修正内容概要
オリジナルのIgoでは、データ読み込みにはnio系パッケージのjava.nio.channels.FileChannelとjava.nio.MappedByteBufferを使っていた。
// MappedByteBufferを使ったデータ(int列)読み込み例 FileChannel in = new FileInputStream("/path/to/dic-data").getChannel(); MappedByteBuffer buffer = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size()); int[] data = new int[(int)in.size()/4]; buffer.asIntBuffer().get(data);
この方法だとバイナリファイルのデータを高速に読み出すことができる。
ただGoogle App EngineではMappedByteBufferクラスが使用不可となっていたため、初期のigo-gae(ver0.0.1)ではjava.io.DataInputStreamを使った方法で代替していた。
// DataInputStreamを使ったデータ(int列)読み込み例 DataInputSream in = new DataInputStream(new BufferedInputStream(new FileInputStream("/path/to/dic-data"))); int[] data = new int[new File("/path/to/dic-data").length()/4]; for(int i=0; i < data.length; i++) data[i] = in.readInt();
今回のver0.0.2では、データ読み込み部に再びnio系のパッケージを採用。
MappedByteBufferは使えないので、代わりにjava.nio.ByteBufferを使用。
ByteBufferに対して必要な分(= ファイルサイズ)の領域を明示的に確保し、そこに(コンストラクタ内で)あらかじめファイルの全データを読み込んでおくようにした。
こうしておけば、後の使い方はMappedByteBufferとただのByteBufferの間にほとんど差異はない。
// (マッピングなしの)ByteBufferを使ったデータ(int列)読み込み FileChannel in = new FileInputStream("/path/to/dic-data").getChannel(); ByteBuffer buffer = ByteBuffer.allocateDirect((int)in.size()/4); in.read(buffer); // ここでファイルのデータを全て読み込んでおく buffer.flip(); int[] data = new int[(int)in.size()/4]; buffer.asIntBuffer().get(data);
この方法は、初めのMappedByteBufferを使うものに比べると若干速度は落ちるが、DataInputStreamを使う方法比べればだいぶ高速。
現時点のigo-gaeのサンプルWebアプリ(http://igo-morp.appspot.com/)はver0.0.2のソースで動いているが、スピンアップ時間がver0.0.1では5秒前後掛かっていたのが、現在は2.5秒前後、と半分程度に短縮されていた。