HDFSが高速に?mmapによるzero-copyでの読み込み
本日公開されたHDFSの高速化に関連するJIRAの2つ目です。
通常、アプリケーションはread()などのシステムコール経由でファイルを読み出します。
このHDFS-4953はmmap()システムコールを使用することで、読み取り時にかかるオーバーヘッドを減らそうというものです。
参考までに、通常アプリケーションがファイルを読み出す場合、以下のようなフローでカーネルからの読み込み処理が行われます。
アプリからの読み込み要求
v
fread()など (stdlib)
v
read()システムコール(glibc)
v
(以下カーネル空間)
v
sys_read()
v
vfs_read()
v
….
参考資料:ページキャッシュのメモ P.12
アプリケーションからの読み出し要求によりシステムコールが呼ばれるのは上記の通りですが、問題となるのは、
- read()が頻繁に呼びだされる場合、コンテキストスイッチが多く発生してコストがかかる※コストの計測には strace や valgrind、perfなどが利用できます
- デバイスから読み込んだカーネル空間のデータを、copy_to_user() などによってユーザー空間にコピーする必要がある
mmap()を使用することで、ファイルをメモリにマッピングすることができるようになります。以前の@ITで面白い比較があったので、興味があればご覧になって下さい。
ということで、mmap()により読み取りをゼロコピーにする、というのがこの修正案のようです。
注意しなければならないのは、mmap()システムコール自体のコストはそれなりにかかるので、1)ファイルオープン、2)数バイト読み込み、3) クローズ、というようなアクセスパターンであれば、mmap()よりもread()の方が良いかもしれません。
ただしHDFSのブロックサイズは64MB なので、mmap()の効果は期待できますね。