Linux は、この質問で定義されている「日和見スワッピング」を行いません。
次の主な参考文献では、概念についてまったく言及されていません:
<オール>具体的には:
<ブロック引用>10.6 ページアウトデーモン (kswapd)
歴史的に kswapd
以前は 10 秒ごとにウェイクアップしていましたが、ゾーン内の空きページ数が pages_low に達したときに物理ページ アロケーターによってのみウェイクアップされるようになりました。 [...] 極度のメモリ不足の下では、プロセスは kswapd
の作業を行います 同期的に。 [...] kswapd
pages_high watermark に達するまでページを解放し続けます。
上記に基づいて、空きページ数が「ハイ ウォーターマーク」よりも高い場合、スワッピングは予想されません。
第二に、これは kswapd
の目的を教えてくれます より多くの無料ページを作成することです。
kswapd
のとき スワップするメモリ ページを書き込むと、すぐにメモリ ページが解放されます。 kswapd はスワップされたページのコピーをメモリに保持しません .
Linux 2.6 は「rmap」を使用してページを解放します。 Linux 2.4 では、話はより複雑になりました。ページが複数のプロセスによって共有されている場合、kswapd はそのページをすぐに解放できませんでした。これは古代の歴史です。リンクされた投稿はすべて Linux 2.6 以降に関するものです。
<ブロック引用>交換性
このコントロールは、カーネルがメモリ ページをどの程度積極的にスワップするかを定義するために使用されます。値が高いほど積極性が増し、値が低いほどスワップの量が減少します。値 0 は、空きページとファイルでバックアップされたページの量までスワップを開始しないようにカーネルに指示します。 ゾーンの最高水準点よりも小さいです。
この引用は特別なケースを説明しています:swappiness
を構成する場合 値は 0
になります .この場合、キャッシュ ページの数が最高水準点に達するまで、スワッピングが発生することは期待できません。つまり、カーネルはスワップを開始する前に、ほとんどすべてのファイル キャッシュを破棄しようとします。 (これにより、大幅な速度低下が発生する可能性があります。ファイル キャッシュが必要です。ファイル キャッシュは、実行中のすべてのプログラムのコードを保持するために使用されます :-)
透かしとは?
上記の引用から疑問が生じます:システムの「ウォーターマーク」メモリ予約はどのくらいの大きさですか?回答:「小規模な」システムでは、デフォルトのゾーン ウォーターマークがメモリの 3% 程度になる場合があります。これは、「最小」ウォーターマークの計算によるものです。大規模なシステムでは、透かしの割合は小さくなり、メモリの 0.3% に近づきます。
したがって、質問が 10% を超える空きメモリを持つシステムに関するものである場合、このウォーターマーク ロジックの正確な詳細は重要ではありません。
個々の「ゾーン」の透かしは /proc/zoneinfo
に示されています 、proc(5) で説明されているように。私のゾーン情報からの抜粋:
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 は、RAM (DMA32 ゾーン) の最初の 4GiB の約 1/256 であるため、通常は約 16MiB です。
Linux コードのコミット
<ブロック引用>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:利用可能なメモリをより控えめに見積もる
MemAvailable
/proc/meminfo
のアイテム これは、スワッピングを発生させずに割り当てることができるメモリ量のヒントをユーザーに提供することです。これにより、ゾーンの低水位標がユーザー空間で使用できないものとして除外されます。
ただし、ユーザー空間の割り当ての場合、kswapd
空きページがハイ ウォーターマークとページ アロケータのローメモリ保護の組み合わせに達するまで実際に再利用されます。これにより、ユーザー空間からも一定量の DMA および DMA32 メモリが保持されます。
MemAvailable を計算する際に、空きページ数からユーザー空間で利用できないとわかっている全量を差し引きます。
Linux コード
swappiness
を変更すると主張されることがあります 0
まで 「日和見スワッピング」を効果的に無効にします。これは興味深い調査手段を提供します。 「日和見スワッピング」と呼ばれるものがあり、swappiness によって調整できる場合、vm_swappiness
を読み取るすべての呼び出しチェーンを見つけることで追跡できます。 . CONFIG_MEMCG
と仮定することで検索スペースを減らすことができることに注意してください は設定されていません (つまり、「メモリ cgroups」が無効になっています)。呼び出しチェーンは次のようになります:
- vm_swappiness
- mem_cgroup_swappiness
- get_scan_count
- shrink_node_memcg
- shrink_node
shrink_node_memcg
「これは基本的なノードごとのページ解放です。kswapd と直接再利用の両方で使用されます」とコメントされています。つまりこの関数は、無料の数を増やします ページ。後で解放できるように、ページを複製してスワップしようとしているわけではありません。しかし、それを割り引いても:
上記のチェーンは、以下に示す 3 つの異なる関数から呼び出されます。予想通り、呼び出しサイトを直接回収と直接回収に分けることができます。 kswapd.直接回収で「日和見スワッピング」を実行しても意味がありません。
<オール>/* * This is the direct reclaim path, for page-allocating processes. We only * try to reclaim pages from zones which will satisfy the caller's allocation * request. * * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ static void shrink_zones
* kswapd shrinks a node of pages that are at or below the highest usable * zone that is currently unbalanced. * * Returns true if kswapd scanned at least the requested number of pages to * reclaim or if the lack of progress was due to pages under writeback. * This is used to determine if the scanning priority needs to be raised. */ static bool kswapd_shrink_node
* For kswapd, balance_pgdat() will reclaim pages across a node from zones * that are eligible for use by the caller until at least one zone is * balanced. * * Returns the order kswapd finished reclaiming at. * * kswapd scans the zones in the highmem->normal->dma direction. It skips * zones which have free_pages > high_wmark_pages(zone), but once a zone is * found to have free_pages <= high_wmark_pages(zone), any page in that zone * or lower is eligible for reclaim until at least one usable zone is * balanced. */ static int balance_pgdat
したがって、おそらく、すべてのメモリ割り当てが空きメモリからすぐに満たされている場合でも、kswapd が何らかの方法で起動されるという主張があると思われます。 wake_up_interruptible(&pgdat->kswapd_wait)
の使い方を調べてみました 、このようなウェイクアップは見られません。
いいえ、Linux には日和見スワッピングなどはありません。私はしばらくこの問題を調べましたが、すべての情報源 (教科書、カーネル開発者のメーリング リストの電子メール、Linux のソース コードとコミット コメント、および Mel Gorman との Twitter のやり取り) から同じことがわかりました。何らかの形のメモリ プレッシャーに対応するメモリ (休止状態は明らかな例外を除く)。
この件に関する一般的な誤解はすべて、Linux がスワッピングを開始する前に、空きメモリの最後のバイトまで待つ余裕がないという単純な事実に起因している可能性があります。極端な形のメモリの枯渇から保護するために、ある種のクッションが必要であり、そのクッションのサイズに影響を与える可能性のある調整変数がいくつかあります (例:vm.min_free_kbytes
)。でも「仕方がないから交換」とは違います。
残念ながら、ページ フレーム再利用アルゴリズムは 2.6 に関してははるかに複雑になりました (Mel Gorman の本で詳細に説明されていたとき) が、基本的な考え方はほぼ同じです。起きて kswapd
または、ページを同期的に解放しようとします (メモリ プレッシャ、割り当てフラグ、およびその他の要因に応じて)。
十分な空きメモリが残っている状態でページ割り当てが失敗し始める最も明白な理由は、実際にはメモリが断片化されすぎて要求を満たすことができないにもかかわらず、連続したメモリを要求している可能性があることです。歴史的に、Linux カーネルの開発者は、連続した割り当ての必要性を回避するために多大な努力を払ってきました。それにもかかわらず、一部のデバイス ドライバーでは、マルチページ メモリ I/O (スキャッター ギャザー DMA) を実行できないか、ドライバー開発者によるコーディングが適切でない可能性があるため、依然としてそれが必要です。 Transparent Huge Pages (THP) の出現により、メモリを物理的に連続したチャンクに割り当てるもう 1 つの理由が生まれました。
同じ時期に導入されたゾーン圧縮は、メモリの断片化の問題に役立つはずですが、常に期待どおりの効果が得られるとは限りません。
いろいろな vmscan
があります 特定のケースで何が起こっているかを正確に理解するのに役立つトレースポイント -- 特定のコール スタックがある場合は、リモートで関連するすべてのものをスキャンするよりも、Linux カーネル コードで必要なものを見つける方が常に簡単です。