メモリマップトファイル

メモリマップトファイル（memory-mapped file）はファイルまたはそれに類似するリソース（あるいはその一部）を仮想記憶空間の連続領域に直接マッピングしたものである。そのリソースは通常物理的にディスク上に存在するファイルだが、デバイス、共有メモリオブジェクトなどオペレーティングシステムがファイル記述子で参照できるリソースなら何でもよい。ファイルとメモリ空間の対応付けにより、アプリケーションはそれを主記憶の一部として扱うことができる。 メモリマップトファイルの最大の利点は、I/O性能の向上であり、特に大きなファイルに対して使った際に顕著である。小さなファイルに対して使用すると、メモリへのマッピングはページ単位（通常4KiB）であるためフラグメンテーションによる無駄が生じやすい。例えば5KiBのファイルをマッピングすると8KiBが割り当てられ、3KiBが無駄となる。メモリマップトファイルは通常のリード/ライト操作よりも2つの理由で高速である。1つは、プログラムのローカルメモリの単純な更新に比べ、システムコールは何倍もオーバーヘッドがかかる。2つめは、多くのオペレーティングシステムにおいて実際にマッピングされているメモリはカーネルの管理するページキャッシュ（英語版）（ファイルキャッシュ）だという点で、ユーザー空間にコピーを作成する必要がない。 アプリケーションレベルのメモリマップトファイルも物理的ファイル操作に比べて優れていることが多い。アプリケーションはファイル内のデータを直接その場で更新でき、ファイルの先頭からのシークしたり、更新したコンテンツを一時的に保管するなどの処理が不要となる。メモリマップトファイルは内部ではページ単位で扱われるので、先頭から順にアクセスする場合（例えばフラットファイルデータベースやコンフィギュレーションファイルなどの場合）、新たなページ境界をまたぐときだけディスクアクセスを必要とし、1回の操作でより大きな部分をディスクに書き込むことができる。 メモリマップトファイルの考えられる利点の1つとして「遅延ロード」がある。すなわち、大きなファイルをマッピングしても実際には少量のメモリしか使わない。搭載している物理メモリ量よりずっと大きいファイル全体をロードしようとすると、OSはディスクからメモリへの読み込みとメモリからディスクへの書き出しを同時に行わなくてはならなくなり、頻繁にスラッシングが発生することになる。メモリマッピングはスワップファイルを完全に迂回するだけではなく、データの編集が行われた部分だけを小さなページ単位でロードすればよく、デマンドページング（英語版）の技法と似ている。 メモリマッピング処理はメモリ管理が行い、同じサブシステムがスワップファイルも担当している。メモリマップトファイルはページ単位にメモリにロードされ、ページサイズはOSが性能を最適化するよう選択する。スワップファイル管理は仮想記憶システムの重要な要素であり、ファイルをページ単位でメモリにロードする部分は高度に最適化されているのが一般的である。 メモリマップトファイルが使われる最大の理由は性能である。それでも、そこにはトレードオフが存在しうる。標準I/Oはシステムコールとメモリコピーのオーバーヘッドがあるためコストが高い。メモリマップトファイルのコストはマイナーなページフォールトのコストであり、プロセスの仮想空間にマッピングされていない部分のデータブロックをページキャッシュ（英語版）にロードする際のコストである。状況によってはそのI/Oが多大になり、標準のファイルI/Oより遅くなることもある。 もう1つの欠点として、ファイルが大きすぎて全体を一度にマッピングできない場合がある。その場合、ファイルの一部分のみをマッピングし、必要に応じてマッピングを切り換えることになるが、処理が複雑化する。例えば、インテルのIA-32では、4GiBかそれ以下でしかマッピングできない。 最も一般的な用途は、Microsoft Windows やUnix系のOSにおけるプロセスローダである。プロセスを開始する際にOSはメモリマップトファイルの機構を使って実行ファイルをマッピングし、何らかのローダブルモジュールをマッピングし、実行開始させる。この際にデマンドページング（英語版）という技法を使い、実際に参照を行った部分だけをページ単位に物理メモリにロードする。すなわち、OSは実行ファイルの実行に実際に必須な部分だけを選択的にロードする。 もう1つの一般的用途は、複数プロセス間のメモリ共有に使用する場合である。x86アーキテクチャのプロテクトモードで動作する現代のOSでは、プロセスは他のプロセスに割り当てられたメモリ空間に通常アクセスできない。それを行おうとすると不正ページフォールトまたはセグメンテーション違反が発生する。メモリを共有する技法はいくつかあり、中でもメモリマップトファイルは最も一般的である。複数のアプリケーションが単一の物理ファイルを同時にそれぞれのメモリ空間にマッピングし、同時にアクセスできる。例えば Microsoft Windows はアプリケーションがシステムのページファイル（スワップファイル）自体を共有セグメントにメモリマップする機構を提供しており、それによってデータを共有できる。 現代の多くのオペレーティングシステムやランタイム環境でメモリマップトファイルへのアクセスが何らかの形でサポートされている。 POSIX (mmap) ファイル識別子、ファイル先頭からのオフセット、長さを指定してマッピングを生成する mmap() がPOSIX仕様の一部として定義されており、POSIX準拠の各種システム、UNIX、Linux、macOS、OpenVMS などに実装されている。 Microsoft Windows メモリマップトファイルのためのAPIとして CreateFileMapping() などを用意している。 Boost C++ ライブラリ Microsoft Windows と POSIX準拠プラットフォームのためのメモリマップトファイルの移植性のある実装を提供している。 Java FileChannel など、メモリマップトファイルにアクセスするクラスやメソッドを提供している。 D言語 標準ライブラリ（std.mmfileモジュール）でメモリマップトファイルをサポートしている。 Ruby Mmap というgem（ライブラリ）があり、メモリマップトファイルを実装している。 Python バージョン1.6から標準ライブラリに mmap モジュールが含まれている。実装はプラットフォームが Windows か Unix系かで大きく異なる。 Perl CPANにいくつかのメモリマップトファイル用モジュールがある。例えば、Sys::Mmap や File::Map がある。 .NET Framework P/Invokeで Windows API 経由で直接メモリマップトファイルを使える。P/Invokeを必要としないマネージコードでのメモリマップトファイルはバージョン4から導入された。それ以前のバージョンではサードパーティから同様のライブラリが提供されていた。 PHP かつては file_get_contents() などでメモリマップトファイルを利用していたが、5.3 でそれが削除された。 R言語 CRAN上のライブラリに bigmemory があり、Boost ライブラリのメモリマップトファイルを利用して大規模行列をメモリにマッピングする。 mmap 共有メモリ