仮想メモリマッピングの断片化はパフォーマンスの問題を引き起こしますか?

Does virtual memory mapping fragmentation cause performance issue?


質問 written by Oliv @2019-01-24 09:03:37Z

: 0 : 1 : 66

linux mmapシステムコールを使用して、大規模な匿名マッピング(約4MB)を作成することから始めるアプリケーションがあります。

その後、プロセス実行中に、できるだけ早くメモリを解放するために、最初は大きなブロックであった仮想メモリマッピングが断片化されるように、メモリの小さなチャンクのマッピングを解除することを考えていました。

これにより、仮想メモリ変換テーブルの断片化によるパフォーマンスの問題が発生する可能性がありますか、それともカーネルはそれを回避するためにスマート戦略を使用しますか? 仮想メモリマッピングの断片化について気にしないでください。

回答 1 written by Kristina Brooks @2019-01-24 09:44:43Z
2

簡単な答え:最小粒度(つまり、4096バイト)のランダムな領域を大量にランダムに割り当てない限り、そうではありません。


長い答え:種類、

最新のアーキテクチャでは、複数レベルの仮想メモリマップ(またはページテーブル、任意の用語)があり、64ビットアーキテクチャでは、一般的に48ビットアドレス空間に4レベルのメモリマップがあります(Intelの今後の拡張により、別のレベルが追加されます4096バイトページを256バイトページに断片化できます)。 マップがまだ存在しない領域にページを割り当てるたびに、カーネルは新しい(通常は物理的に連続しています。強調に注意してください。これは相対的な観点ではかなり高価な操作です)メモリチャンクを割り当てて、翻訳マップを保持しますそのメモリ空間のその領域。 アーチ固有の用語は避け、 L0 -> L1 -> L2 -> L3と呼びますL0 -> L1 -> L2 -> L3はその仮想メモリ空​​間を表すルートマップです。 これは、ページサイズの粒度と異なるオペレーティングシステムまたはアーキテクチャによって異なります(たとえば、Linuxにはスーパーページがあります)。

これで、新しいマッピングがL3レベルにあり、L3ページテーブルがある場合、新しいマッピングでは、その領域のエントリを変更して翻訳を示すだけです。 L3ページテーブルがない場合、新しいL3ページテーブルを割り当て、L2ページテーブルに入力する必要があります。 L0ページのテーブルまで続きます。

いくつかの簡単なメモ:

  • マッピングが変更されるたびに、通常、TLB(変換ルックアサイドバッファ。VM-> Phys変換のためにMMUが使用するハードウェアキャッシュ)無効化ペナルティ(手動または自動)があります。
  • 一部のページは翻訳の4段階すべてを必要としない場合があり、翻訳レベルには特定のサイズがあります。そのため、スーパーページは通常、たとえばL2ページテーブルエントリを使用してそのVMスペースのチャンク全体を物理スペースにマッピングするページです(これは、 3レベルの翻訳のみが必要です)。
  • さまざまなアーキテクチャがTLBトラッシングのペナルティを減らすために異なる方法を使用します(つまり、x86_64のPCID。実際、KPTIのような一部のメルトダウンの緩和により、それなしでパフォーマンスが低下しました)。
  • メルトダウンといえば、メモリの範囲によっては、カーネルまたはトランポリンのマッピングまたは例外ベクトルが含まれる場合があります。 これらはOSによって予約されています。 Spectre / Meltdownより前の64ビットシステムでは、カーネルがすべてのページテーブルにマップされたままになるのが一般的でした。 多くのARMプロセッサには、スプリットページテーブル(TTBR0 / TTBR1;変換テーブルベースレジスタ0/1)と呼ばれる専用のメカニズムがあります。
  • 上記の1つの例は、カーネルによって作成されたマッピングであるLinux VDSO(仮想動的共有オブジェクト)です。 それに対応するDarwin(OSX / iOS)は、commpage(共通ページ)です。 これには通常、システム内のすべてのプロセスによって共有される読み取り専用コードがあり、現在のものがあります(syscallのコストを削減するために、 gettimeofdayはVDSOから読み取るか、VDSOトランポリンを使用して読み取ることができます)。
  • もちろん、上記のすべては、使用しているアーキテクチャとOS、および使用しているOSのバージョンによって異なります。これは、仮想メモリマネージャーがさまざまな手法を使用してフラグメンテーションが発生しないようにするためです。 ただし、多数の小さな固定マッピングをランダムにリクエストすると、はい、事実上多くのマッピングをバイパスすることになり、パフォーマンスの問題が発生します。
コメント 1

理解しようとしています。mmapを作成し、L3ページテーブルに完全に収まると仮定します(たとえば、仮想メモリページ1〜10は物理メモリA〜Jに関連付けられています)。たとえば、仮想メモリページ2、5、8のマッピングを解除した場合、カーネルはL2ページテーブルを作成しません。これは、2、5、8が以前に割り当てられたL3ページテーブル内にあるためです。正しい?(1)

written by オリヴ @2019-01-25 09:00:07Z

コメント 2

それにもかかわらず、2、5、8(B、E、H)に関連付けられた物理メモリは、他のプロセスによって再利用される可能性はありますか?(2)

written by オリヴ @2019-01-25 09:01:28Z

コメント 3

カーネルはページフォールトで物理メモリを割り当てませんか?ページフォールトの粒度はどのくらいですか?メモリマッピング全体(たとえば、最初に1のバイト、カーネルフォールト1-10にアクセスし、AからJを予約した場合)か、物理メモリの1ページのみを予約しますか?(3)

written by オリヴ @2019-01-25 09:05:24Z

コメント 4

また、クリスティーナの詳細な説明をありがとうございます:)。

written by オリヴ @2019-01-25 09:06:11Z

コメント 5

前回チェックしたとき(Linux 2.6)、新しいバイナリはマップされなかったため、最初は新しいページからの読み取りごとにページフォールトが発生しましたが、これはディスク/ブロックキャッシュレイヤーまで落ちていました。ASLRでは、セキュリティを損なうことなくページテーブルを共有することは難しく、またそのようなページのコードは完全にPICである必要があるため(PC相対のみ、別名再配置を必要としないため、VDSOの仕組み) )。

written by クリスティーナブルックス @2019-01-26 14:19:51Z