1

実験は Linux、x86 32 ビット上で行われます。

したがって、私のアセンブリ プログラムで、定期的に (たとえば、100000 個の基本ブロックを実行した後は毎回)、.bss セクションの配列をメモリからディスクにダンプする必要があるとします。配列の開始アドレスとサイズは固定されています。配列は実行された基本ブロックのアドレスを記録し、サイズは現在 16M です。

memcpy.bss セクションからスタックにネイティブ コードを書き込んでから、ディスクに書き戻そうとしました。しかし、それは非常に面倒なようで、パフォーマンスとメモリ消費が心配です。たとえば、スタックに非常に大きなメモリを割り当てるたびに...

これが私の質問です。グローバルデータセクションからメモリを効率的にダンプするにはどうすればよいですか? 私は十分に明確ですか?

4

2 に答える 2

2

まず、コードのこの部分を asm 、espで記述しないでください。最初ではありません。この部分を処理する C 関数を作成し、asm から呼び出します。別の 16MiB をダンプするときにのみ実行される部分をパフォーマンス調整する必要がある場合は、手動で調整できます。システムレベルのプログラミングは、システムコール (または C stdio 関数) からのエラーリターンをチェックすることがすべてであり、asm でそれを行うのは面倒です。

システム コールの作成は C と比較して特別なことではないため、明らかに asm で何でも記述できます。また、C と比較して asm の方が簡単な部分はありませんMFENCE

とにかく、私はあなたがバッファで何をしたいのかについて3つのバリエーションに対処しました:

  1. 同じバッファを上書きします ( mmap(2)/ msync(2))
  2. バッファーのスナップショットをファイルに追加します (write(2)またはおそらく機能しないゼロコピーvmsplice(2)+splice(2)アイデアを使用して)。
  3. 古いバッファを書き込んだ後、新しい (ゼロ化された) バッファを開始します。 mmap(2)出力ファイルの順次チャンク。

インプレース上書き

毎回ディスクの同じ領域を上書きしたい場合はmmap(2)、ファイルを作成して、それをアレイとして使用します。(データを強制的にディスクに書き込むために定期的に呼び出しmsync(2)ます。) ただし、mmapped メソッドは、ファイルの一貫した状態を保証しません。書き込みは、要求があった場合以外にディスクにフラッシュされる可能性があります。何らかの保証でそれを回避する方法がある場合はIDK(つまり、バッファフラッシュタイマーなどを選択するだけでなく、通常、msync(2).

スナップショットを追加

バッファをファイルに追加する簡単な方法は、書き込みたいときに呼び出すだけwrite(2)です。 write(2)必要なすべてを行います。プログラムがマルチスレッドの場合、システム コールの前にデータをロックし、後でロックを解除する必要がある場合があります。write システム コールがどれだけ速く返されるかはわかりません。カーネルがデータをページキャッシュにコピーした後にのみ返される場合があります。

スナップショットが必要なだけで、バッファへのすべての書き込みがアトミック トランザクションである場合 (つまり、互いに一貫性を保つ必要がある値のペアではなく、バッファが常に一貫した状態にある場合)、スナップショットを取得する必要はありません。を呼び出す前にロックしwrite(2)ます。この場合、わずかな偏りがあります (カーネルが順番にコピーすると仮定すると、バッファーの最後のデータは最初のデータよりも少し後の時間からのものになります)。

write(2)ダイレクト IO (ゼロコピー、ページキャッシュのバイパス) で IDKが遅くなったり速くなったりする場合。open(2)あなたのファイルはO_DIRECTwrite(2)通常は.

バッファのスナップショットを書き込んで変更し続ける場合は、プロセスのどこかにコピーが必要です。または、MMU コピー オン ライトのトリック:

ゼロコピー追加スナップショット

ユーザーページのディスクファイルへのゼロコピー書き込みを行うための API があります。Linux のvmsplice(2)splice(2)この順序で、ページをページ キャッシュにマップするようにカーネルに指示できます。がなければSPLICE_F_GIFT、コピーオンライトとして設定すると思います。(おっと、実際にはmanページには without と書かれていますがSPLICE_F_GIFT、以下splice(2)はコピーする必要があります。したがって、コピーオンライトセマンティクスを取得するメカニズムがある場合はIDKです。)

カーネルがディスクへの書き込みを完了して解放できるようになるまで、ページのコピー オン ライト セマンティクスを取得する方法があると仮定します。

さらに書き込みを行うには、データがディスクにヒットする前にカーネルが 1 ページまたは 2 ページを memcpy する必要があるかもしれませんが、バッファー全体をコピーする必要はありません。ソフト ページ フォールトとページ テーブル操作のオーバーヘッドは、書き込みがディスクにヒットし、書き込み対象のページが解放されるまでの短い期間にデータ アクセス パターンが非常に空間的に局所化されていない限り、いずれにしても価値がない可能性があります。(このように動作する API は存在しないと思います。なぜなら、ページがディスクにヒットした直後にページを解放するメカニズムがないからです。Linux はそれらを引き継いで、ページ キャッシュに保持したいと考えています。)

私は vmsplice を使用したことがないので、詳細が間違っている可能性があります。

同じメモリの新しいコピー オン ライト マッピングを作成する方法がある場合、おそらくmmapスクラッチ ファイル (tmpfs ファイル システム上) の新しいマッピングを作成することによって/dev/shm、ロックを長時間保持せずにスナップショットを取得できます。 . 次に、スナップショットを に渡すだけでwrite(2)、コピー オン ライト ページ フォールトが多く発生する前にできるだけ早くマップを解除できます。

チャンクごとに新しいバッファ

すべての書き込み後にバッファをゼロにして開始しても問題ない場合mmap(2)は、ファイルの連続したチャンクを作成できるため、生成するデータは常に適切な場所にあります。

  • (オプション)fallocate(2)書き込みパターンがシーケンシャルでない場合に断片化を防ぐために、出力ファイルにいくらかのスペース。
  • mmap(2)出力ファイルの最初の 16MiB にバッファを追加します。
  • 普通に走る
  • 次の 16MiB に移動する場合:
    1. ロックを取得して、他のスレッドがバッファを使用できないようにする
    2. munmap(2)あなたのバッファ
    3. mmap(2)ファイルの次の 16MiB を同じアドレスに転送するため、新しいアドレスをライターに渡す必要はありません。これらのページは、POSIX の要求に応じて事前にゼロ化されます (カーネルがメモリを公開することはできません)。
    4. ロックを解除する

おそらく/ペア mmap(buf, 16MiB, ... MAP_FIXED, fd, new_offset)を置き換えることができます。重複する古いイングを破棄します。これは、ファイル/共有メモリへの変更が破棄されることを意味するのではなく、実際のマッピングが変更されることを意味すると思います。munmapmmapMAP_FIXEDmmapmunmap

于 2015-07-18T09:13:02.370 に答える
1

ピーターの回答からスナップショットを追加する場合の 2 つの説明。

1. なしで追加O_DIRECT

ピーターが言ったように、を使用しない場合O_DIRECTwrite()データがページ キャッシュにコピーされるとすぐに返されます。ページ キャッシュがいっぱいになると、古いページがディスクにフラッシュされるまでブロックされます。

データを読み取らずに追加するだけの場合 (まもなく)、sync_file_range(2)以前に書き込まれたページのフラッシュをスケジュールするために定期的に呼び出すことと、既にフラッシュされたページをページ キャッシュから削除するフラグをposix_fadvise(2)使用することでメリットが得られます。POSIX_FADV_DONTNEEDこれにより、ブロックされる可能性が大幅に減少する可能性がありwrite()ます。

2. で追加O_DIRECT

ではO_DIRECTwrite()通常、データがディスクに送信されるまでブロックされます (厳密には保証されていませんが、こちらを参照してください)。これは遅いため、ノンブロッキング書き込みが必要な場合は、独自の I/O スケジューリングを実装する準備をしてください。

アーカイブできる利点は次のとおりです。より予測可能な動作 (いつブロックするかを制御できます) と、アプリケーションとカーネルのコラボレーションによるメモリと CPU の使用量のおそらく削減です。

于 2015-07-23T10:52:53.513 に答える