9

仮説として、非常に大きな可能性のあるファイルに順次書き込みを実行したいとします。

巨大な領域を mmap() し、その領域全体で madvise(MADV_SEQUENTIAL) を実行すると、比較的効率的な方法でメモリに書き込むことができます。これで問題なく動作するようになりました。

現在、執筆中にさまざまな OS リソースを解放するために、既に書き込まれているメモリの小さなチャンクに対して munmap() を実行することがあります。私の懸念は、データがディスクに物理的にコミットされるのを待って、munmap() と msync() が私のスレッドをブロックすることです。ライターの速度をまったく落とすことができないので、別の方法を見つける必要があります。

既に書き込まれた小さなメモリ チャンクに対して madvise(MADV_DONTNEED) を使用する方が良いでしょうか? そのメモリを遅延してディスクに書き込み、呼び出し元のスレッドをブロックしないように OS に指示したいと考えています。

madvise() のマンページには次のように書かれていますが、これはかなりあいまいです。

MADV_DONTNEED
Do  not expect access in the near future.  (For the time being, the 
application is finished with the given range, so the kernel can free
resources associated with it.)  Subsequent accesses of pages in this
range will succeed, but will result either in re-loading  of the memory
contents from the underlying mapped file (see mmap(2)) or
zero-fill-on-demand pages for mappings without an underlying file.
4

4 に答える 4

20

いいえ!

あなた自身のために、近づかないでくださいMADV_DONTNEED。Linux はこれをヒントとして、ページを書き戻した後にページを破棄するのではなく、すぐに破棄するようにします。これはバグではなく、意図的な決定です。

皮肉なことに、非破壊の機能MADV_DONTNEEDはすでに によって与えられているのに対しmsync(MS_INVALIDATE|MS_ASYNC)MS_ASYNCは I/O を開始しないというのが理由です (実際、ダーティ ページの書き戻しが問題なく機能するという理由に従って、何もしません)。fsync常にブロックし、あいまいな制限を超えてドキュメントによって「非常に危険」と見なされた場合sync_file_range はブロックする可能性があります。

いずれにせよmsync(MS_SYNC)、 またはfsync(両方ともブロック) またはsync_file_range(おそらくブロック) の後に を指定fsyncする必要があります。そうしないと、 でデータ失われますMADV_DONTNEED。ブロックする余裕がない場合は、悲しいことに、別のスレッドでこれを行うしかありません。

于 2013-10-29T14:34:13.617 に答える
3

最近の Linux カーネル (Linux 5.4 でテストしたばかり) ではMADV_DONTNEED、マッピングが非公開(フラグmmapなしなど) の場合に期待どおりに動作します。MAP_PRIVATE以前のバージョンの Linux カーネルでの動作はわかりません。

Linux man-pages プロジェクトのmadviseマンページのリリース 4.15 から:

操作が成功MADV_DONTNEEDすると、指定された領域でのメモリ アクセスのセマンティクスが変更されます。範囲内のページへの後続のアクセスは成功しますが、基になるマップ ファイルの最新の内容からメモリの内容を再設定することになります (共有ファイル マッピング、共有匿名マッピング、および System V 共有メモリ セグメントなどの shmem ベースの手法の場合)または匿名プライベート マッピングのゼロ フィル オンデマンド ページ。

Linux は、 Linux 4.5MADV_FREEの BSD システムで同じ動作をする新しいフラグを追加しました。

必要に応じてページを解放可能としてマークするだけですが、すぐに解放するわけではないため、ページを再度フォールトするコストを負担することなくメモリ範囲を再利用できます。

MADV_DONTNEEDプライベート マッピングの場合、将来のアクセス時にページがゼロになる可能性がある理由については、@Damon の回答のコメントに記載されているBryan Cantrill の暴言をご覧ください。ネタバレ: これは Tru64 UNIX から来ています。

于 2021-05-14T15:00:45.507 に答える
0

まず、madv_sequential はアグレッシブな先読みを有効にするため、必要ありません。第二に、何もしなくても、os はディスクにダーティ ファイルを焼き付けたメモリを遅延して書き込みます。しかし、 madv_dontneed はすぐにメモリを解放するように指示します (「さまざまな OS リソース」と呼ばれるもの)。第 3 に、シーケンシャル書き込み用にファイルを mmap することに利点があるかどうかは明らかではありません。おそらく、 write(2) だけでより良いサービスが提供されるでしょう(ただし、手動または標準入出力のいずれかのバッファを使用してください)。

于 2013-02-20T02:26:42.530 に答える