プログラムがメモリを要求したが、十分な空きメモリが残っていないとします。 Linuxが応答する方法はいくつかあります。 1つの応答は、最近アクセスされていない他の使用済みメモリを選択し、この非アクティブなメモリをスワップに移動することです。
しかし、これを超える記事やコメントがたくさんあります。空きメモリが大量にある場合でも、Linuxは非アクティブなメモリをスワップに書き込むことを決定することがあります。事前にスワップへの書き込みを行うと、最終的にこのメモリを使用するときに、ディスクへの書き込みを待つ必要がなくなります。彼らは、これはパフォーマンスを最適化するための意図的な戦略だと言っています。
彼らは正しいですか?それとも神話ですか?出典を引用してください。
次の定義を使用して、この質問を理解してください。
/proc/meminfo
のMemFree
値です。 /proc/meminfo
は、カーネルによって提供される仮想テキストファイルです。 proc(5) または RHEL docs を参照してください。ここにいくつかの検索用語があります: linux "opportunistic swapping" OR(swap "when the system has no good better" "OR when when OR "システムがアイドル状態のとき" OR "アイドル時間中")
Googleで2番目に高い結果で、StackExchangeユーザーは「RAMに十分な空き容量があるのになぜスワップを使用するのですか?」と尋ね、約20%の空きメモリを示すfree
コマンドの結果をコピーします。この特定の質問への回答として、私はこの回答が非常に投票されているのを見る:
LinuxはRAMがいっぱいになる前にスワッピングを開始します。これは、パフォーマンスと応答性を向上させるために行われます。
RAMは、プログラムメモリを格納するよりもディスクキャッシュに使用する方がよいため、パフォーマンスが向上します。そのため、しばらく使用されていないプログラムをスワップアウトし、代わりに頻繁に使用するファイルを保持することをお勧めします。キャッシュ。
メモリがいっぱいで、一部のプログラムが実行中であり、タスクを完了するためにさらにRAM=)を要求しているときではなく、システムがアイドル状態のときにページをスワップアウトすることにより、応答性が向上します。
もちろんスワッピングはシステムを遅くします—しかし、スワッピングの代替手段はスワッピングではなく、より多くのRAMまたはより少ないRAMを使用しています。
Googleでの最初の結果は、上記の質問の複製としてマークされています:-)。この場合、質問者は16GBのうち7GB MemFree
を示す詳細をコピーしました。質問には、独自の受け入れられ、賛成された回答があります。
空きメモリがない場合にのみスワッピングが発生するのは、
swappiness
を0に設定した場合のみです。それ以外の場合は、アイドル時にカーネルがメモリをスワップします。これを行う際、データはメモリから削除されず、スワップパーティションにコピーが作成されます。これは、メモリが使い果たされた状況が発生した場合に、その場でディスクに書き込む必要がないことを意味します。この場合、カーネルはすでにスワップされているメモリページを上書きするだけでよく、そのため、データのコピーがあることがわかります。
swappiness
パラメータは基本的に、これをどの程度行うかを制御するだけです。
他の引用は、スワップされたデータがメモリに保持されることを明示的に主張していません。しかし、20%の空きメモリがある場合でもスワップする場合、その方法を選択するように思われます。これを行う理由は、パフォーマンスを向上させるためです。
私の知る限り、Linuxは同じデータのコピーをメインメモリとスワップ領域の両方に保持することをサポートしています。
また、「日和見スワッピング」は「アイドル時間中に」発生するという一般的な主張にも気付きました。この機能は一般的にパフォーマンスに優れていることを確信させるのに役立つと思います。上記の私の定義にはこれを含めません。ニースの明確な質問をするのに十分な詳細がすでにあるからです。これを必要以上に複雑にしたくありません。
ギガバイトの空きメモリがある場合、上部に「swout」(スワッピング)が表示されます。なぜですか?
このように、空きメモリが十分にあるときにLinuxがswapに書き込むという報告がいくつかあります。 「日和見スワップ」はこれらのレポートを説明するかもしれません。同時に、少なくとも1つの代替原因が提案されました。考えられる原因を調べる最初のステップとして、Linuxは上記で定義された「日和見スワップ」を実行しますか?
私が報告した例では、質問が答えられました。原因は日和見交換ではありませんでした。
Linuxは、この質問で定義されている「日和見スワップ」を行いません。
次の主な参考資料では、概念についてまったく触れていません。
すなわち:
歴史的に
kswapd
は10秒ごとにウェイクアップするのに使用されていましたが、現在は、ゾーンのpages_low空きページ数に達したときにのみ物理ページアロケーターによってウェイクアップされます。 [...]極端なメモリ負荷の下で、プロセスはkswapd
の作業を同期的に実行します。 [...]kswapd
は、pages_highウォーターマークに達するまでページを解放し続けます。
上記に基づいて、空きページの数が「最高水準点」よりも高い場合、スワッピングは予想されません。
次に、これはkswapd
の目的がより多くの空きページを作成することであることを示しています。
kswapd
がスワップするメモリページを書き込むと、すぐにメモリページが解放されます。 kswapdはスワップされたページのコピーをメモリに保持しません。
Linux 2.6は、「 rmap 」を使用してページを解放します。 Linux 2.4では、話はもっと複雑でした。ページが複数のプロセスで共有されている場合、kswapdはページをすぐに解放できませんでした。これは古代の歴史です。リンクされているすべての投稿は、Linux 2.6以降に関するものです。
このコントロールは、カーネルがメモリページをどの程度積極的にスワップするかを定義するために使用されます。値が大きいほど攻撃性が高くなり、値が小さいほどスワップ量が少なくなります。値0は、空きおよびファイルに裏付けされたページの量がゾーンの最高水準点を下回るまで、スワップを開始しないようにカーネルに指示します。
この引用は、特別な場合について説明しています:swappiness
値を_0
_に構成した場合。この場合、さらに cache ページの数が最高水準点に落ちるまでスワッピングを予期しないでください。つまり、カーネルは、スワップを開始する前に、ほとんどすべてのファイルキャッシュを破棄しようとします。 (これは大幅な速度低下を引き起こす可能性があります。ファイルキャッシュが必要です!ファイルキャッシュは、実行中のすべてのプログラムのコードを保持するために使用されます:-)
上記の引用は問題を提起します: 私のシステムでの「ウォーターマーク」メモリ予約の大きさは? 回答:「小さな」システムでは、デフォルトのゾーンウォーターマークがメモリの3%と同じくらい高い場合があります。これは、「最小」の透かしの計算によるものです。大規模なシステムでは、透かしの割合は小さくなり、メモリの0.3%に近づきます。
したがって、問題が10%を超える空きメモリを持つシステムに関するものである場合、この透かしロジックの正確な詳細は重要ではありません。
proc(5) に記載されているように、個々の「ゾーン」の透かしは_/proc/zoneinfo
_に示されています。私のzoneinfoからの抜粋:
_Node 0, zone DMA32
pages free 304988
min 7250
low 9062
high 10874
spanned 1044480
present 888973
managed 872457
protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone Normal
pages free 11977
min 9611
low 12013
high 14415
spanned 1173504
present 1173504
managed 1134236
protection: (0, 0, 0, 0, 0)
_
現在の「透かし」は、min
、low
、およびhigh
です。プログラムがfree
をmin
未満に減らすのに十分なメモリを要求した場合、プログラムは「直接再利用」に入ります。カーネルがメモリを解放する間、プログラムは待機させられます。
可能であれば、直接の回収は避けたいと考えています。したがって、free
がlow
のウォーターマークを下回ると、カーネルはkswapd
を起動します。 kswapd
は、free
がhigh
を再び超えるまで、キャッシュのスワッピングやドロップによってメモリを解放します。
追加の資格:kswapd
も実行され、カーネルのlowmemおよびDMA使用法の場合、lowmem_reserveの全量を保護します。デフォルトの lowmem_reserve は約1/256です。 RAM(DMA32ゾーン)の最初の4GiBなので、通常は約16MiBです。
mm:kswapdウォーターマークをメモリに比例してスケール
[...]
watermark_scale_factor:
この要素は、kswapdの積極性を制御します。これは、kswapdがウェイクアップする前にノード/システムに残っているメモリの量と、kswapdがスリープ状態に戻る前に解放する必要があるメモリの量を定義します。
単位は10,000分数です。デフォルト値の10は、透かし間の距離がノード/システムで利用可能なメモリの0.1%であることを意味します。最大値は1000、つまりメモリの10%です。
直接再利用(allocstall)またはkswapdが途中でスリープ状態になる(kswapd_low_wmark_hit_quickly)スレッドが頻繁に発生する場合は、システムで発生している割り当てバーストに対して、遅延の理由でkswapdが保持する空きページの数が少なすぎることを示している可能性があります。このノブを使用して、それに応じてkswapdの積極性を調整できます。
proc:meminfo:使用可能なメモリをより控えめに見積もる
_
/proc/meminfo
_のMemAvailable
アイテムは、スワップを発生させずに割り当て可能なメモリ量のヒントをユーザーに提供するため、ユーザー空間で使用できないゾーンの最低水準点を除外します。ただし、ユーザースペース割り当ての場合、
kswapd
は実際に、空きページが上限とページアロケーターのlowmem保護の組み合わせに到達するまで再利用します。これにより、DMAおよびユーザースペースからのDMA32メモリ。MemAvailableを計算するときは、空き領域の数からユーザースペースで利用できないことがわかっている全量を差し引きます。
swappiness
を_0
_に変更すると、「日和見スワッピング」が事実上無効になると主張されています。これは興味深い調査の道を提供します。 「日和見スワッピング」と呼ばれるものがあり、それをswappinessによって調整できる場合は、_vm_swappiness
_を読み取るすべての呼び出しチェーンを見つけることで追跡できます。 _CONFIG_MEMCG
_が設定されていない(つまり、「メモリcgroup」が無効になっている)と想定することで、検索スペースを削減できることに注意してください。コールチェーンは次のようになります。
_shrink_node_memcg
_は「これは基本的なノードごとのページ解放機能です。kswapdと直接再利用の両方で使用されます」とコメントされています。つまりこの関数は、 自由 ページ。ページを複製してスワップするのではなく、後で解放できるようにします。しかし、それを割り引いても:
上記のチェーンは、次に示す3つの異なる関数から呼び出されます。予想通り、呼び出しサイトを直接再利用対に分割できます。 kswapd。直接再生で「日和見スワッピング」を実行しても意味がありません。
/* *これは、ページ割り当てプロセスの直接再利用パスです。私たちだけ *呼び出し元の割り当てを満たすゾーンからページを再利用しようとします *リクエスト。 * *ゾーンが固定されていると思われる場合ページはそれからそれを軽くします *スキャンしてそれをあきらめます。 */ static void shrink_zones
* kswapdは、使用可能な最も高い ゾーン以下のページのノードを縮小します。 * * * kswapdが最小要求ページ数 *再利用するか、進捗状況がライトバック中のページが原因であったかどうか。 *これは、スキャンの優先度を上げる必要があるかどうかを判断するために使用されます。 。] */ static bool kswapd_shrink_node
* kswapdの場合、balance_pgdat()はゾーンからノード全体のページを再利用します *少なくとも1つのゾーンがバランスするまで呼び出し元による使用に適格なページです。 ____。] * * kswapdが再生を完了した順序を返します。 * * kswapdはゾーンをhighmem-> normal-> dma方向にスキャンします。 * free_pages> high_wmark_pages(zone)を持つゾーンをスキップしますが、ゾーンが * free_pages <= high_wmark_pages(zone)を持つことが判明すると、そのゾーン内のすべてのページ *以下は、少なくとも1つの使用可能なゾーンが平衡化されるまで再利用の対象となります *平衡化されます。 */ 静的整数 バランス_pgdat
したがって、おそらく、すべてのメモリ割り当てが空きメモリからすぐに満たされている場合でも、kswapdが何らかの形で起動されるという主張です。 wake_up_interruptible(&pgdat->kswapd_wait)
の使用方法を調べましたが、このようなウェイクアップは見られません。
いいえ、Linuxには日和見スワップなどはありません。私はしばらく問題を見て、すべてのソース(教科書、カーネル開発者のメーリングリストのメール、Linuxソースコードとコミットコメント、およびTwitterとMel Gormanとのやり取り)が同じことを言っている:Linuxのみが再利用している何らかの形のメモリプレッシャーへの応答としてのメモリ(ハイバネーションの明らかな例外を除く)。
この話題に関するよくある誤解はすべて、Linuxがスワップを開始する前に空きメモリの最後のバイトまで待つことができないという単純な事実に起因していると考えられます。極端な形のメモリの枯渇から保護するために、ある種のクッションが必要であり、そのクッションのサイズに影響を与える可能性のあるいくつかの調整パラメータがあります(例:vm.min_free_kbytes
)。しかし、「やりたいことは何もないので入れ替え」と同じではありません。
残念ながら、ページフレームの再利用アルゴリズムは2.6(Mel Gormanの本で詳細に説明されている場合)に比べてはるかに複雑になりましたが、基本的な考え方はほぼ同じです。ページの再利用は、失敗した割り当てによってトリガーされます。 kswapd
をウェイクアップするか、ページを同期的に解放してみてください(メモリプレッシャー、割り当てフラグ、およびその他の要因によって異なります)。
十分な空きメモリが残っている状態でページ割り当てが失敗し始める最も明白な理由は、実際にはメモリが断片化されすぎて要求を満たすことができず、連続メモリを要求している可能性があるためです。歴史的に、Linuxカーネル開発者は、連続した割り当ての必要性を回避するために多大な努力を払いました。それにもかかわらず、一部のデバイスドライバーは、マルチページメモリI/O(スキャッターギャザーDMA)を実行できないため、またはドライバー開発者によるずさんなコーディングである可能性があるため、依然としてそれを必要とします。 Transparent Huge Pages(THP)の登場により、物理的に隣接するチャンクでメモリを割り当てるもう1つの理由が生まれました。
ほぼ同じ時期に導入されたゾーン圧縮は、メモリの断片化の問題を解決すると思われますが、必ずしも期待した効果が得られるとは限りません。
特定のケースで正確に何が行われているのかを理解するのに役立つさまざまなvmscan
トレースポイントがあります。特定のコールスタックがある場合、Linuxカーネルコードで必要なものを見つけるのは、探しているすべてをスキャンするだけでなく、常に簡単です。リモートで関連性があります。