ダイレクトバッファについて調べる機会
きっかけは、Apache spark でアプリケーション動かしていた時に、java.lang.OutOfMemoryError: Direct buffer memory に出くわしたこと。
ダイレクトバッファのこともよく理解せずに、spark プログラミングするのは申し訳ない気持ちになったので。。
ダイレクトバッファとは
- ダイレクトバッファは、NIOで新しく導入された機能。
- 「ヒープ」外のメモリ領域に作成される。
- 「ヒープ」上に作成される通常のバッファ(非ダイレクトバッファ)に比べて高速。
- ダイレクトバッファはByteBufferについてのみ作成可能。
- 高速に入出力できるが、作成や削除の処理は非ダイレクトバッファより時間がかかる。
- 容量の大きいバッファが必要なとき、作成したバッファを繰り返し使用するときに使用するべき。
バッファとは
- プリミティブ型のデータを保存するための入れ物。
- バッファクラス(ByteBuffer, IntBuffer など)は、boolean型以外のすべてのプリミティブ型に対して用意されている。
- バッファクラスは、java.nioパッケージに属していて、java.nio.Bufferクラスを継承している。
NIO(New I/O)とは
- JDK1.4で追加された機能。java.ioパッケージの入出力機能を補足する。
java.ioパッケージとは
- データ入出力用のクラスがまとめられているパッケージ。
ダイレクトバッファをつくってみる
ダイレクトバッファの作成
ByteBuffer bufferA = ByteBuffer.allocateDirect(5);
非ダイレクトバッファの作成
ByteBuffer bufferB = ByteBuffer.allocate(5);
Java/TryDirectBuffer.java at master · blueskyarea/Java · GitHub
ダイレクトバッファは作成遅いが、アクセス速い
-- allocate direct buffer -- 1002647 nano seconds -- allocate non-direct buffer -- 80622 nano seconds -- access to direct buffer 100000 times -- 16322116 nano seconds -- access to non-direct buffer 100000 times -- 29337490 nano seconds
上記の結果から、以下の点について軽く確認できました。
- ダイレクトバッファは、非ダイレクトバッファよりも作成に時間がかかる。
- ダイレクトバッファは、非ダイレクトバッファよりも繰り返されるアクセスに対して速い。
そういえば、ダイレクトバッファは「ヒープ外」に存在するのだから、GCの対象外になるはず。
なので、十分に大きな値を上限値として割り当てることが推奨されるのかもしれない。