web-dev-qa-db-ja.com

「キャッシュされた」メモリは事実上無料ですか?

実行中cat /proc/meminfo、上部に次の3つの値が表示されます。

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

私の知る限り、「Cached」の値はLinuxシステムによって作成されたディスクキャッシュであり、アプリケーションがより多くのRAMを必要とするとすぐに解放されるため、MemFreeとCachedの両方がゼロになるまでLinuxがメモリ不足になることはありません。

残念ながら、 "MemAvailable"は/ proc/meminfoによって報告されません。おそらく、仮想サーバーで実行されているためです。 (カーネルバージョンは4.4)

したがって、すべての実用的な目的のために、アプリケーションで使用できるRAMはMemFree + Cachedです。

その見方は正しいですか?

11
Roland Seuhs

その見方は、多くの現実のケースで非常に誤解を招く可能性があります。

カーネルはMemAvailableフィールドで利用可能なメモリの見積もりを提供します。この値はMemFree + Cachedとは大きく異なります。

/ proc/meminfo:推定使用可能メモリを提供 [カーネル変更の説明、2014]

多くのロードバランシングおよびワークロード配置プログラムは、/ proc/meminfoをチェックして、使用可能な空きメモリの量を見積もります。彼らは通常、「free」と「cached」を合計することでこれを行います。これは10年前は問題ありませんでしたが、今日は間違いであることがほぼ保証されています。

Cachedには、ページキャッシュとして解放できないメモリ(共有メモリセグメント、tmpfs、ramfsなど)が含まれており、ほとんどがアイドル状態のシステムでシステムメモリの大部分を占める可能性のある再生可能なスラブメモリが含まれていないため、誤りですたくさんのファイル。

現在、システムをスワップにプッシュせずに新しいワークロードに使用できるメモリの量は、MemFree、Active(file)、Inactive(file)、SReclaimable、および/からの「低い」ウォーターマークから推定できます。 proc/zoneinfo。ただし、これは将来変更される可能性があり、ユーザー空間は実際にカーネルの内部を認識して空きメモリの量の見積もりを出すことを期待されるべきではありません。/proc/meminfoでそのような見積もりを提供する方が便利です。将来、状況が変わっても、1か所で変更すればよいのです。
...

Documentation/filesystems/proc.txt:
...
MemAvailable:スワップせずに新しいアプリケーションを開始するために使用できるメモリの推定量。 MemFree、SReclaimable、ファイルLRUリストのサイズ、および各ゾーンの最低水準点から計算されます。この見積もりでは、システムが適切に機能するためにページキャッシュが必要であること、およびアイテムが使用されているためにすべての再生可能なスラブが再生可能であるとは限らないことを考慮しています。これらの要因の影響は、システムによって異なります。

1. MemAvailableの詳細

上記のように、tmpfsとその他のShmemメモリは解放できず、スワップに移動するだけです。 Cached in /proc/meminfoは、このスワップ可能なShmemメモリを含むため、非常に誤解を招く可能性があります。 tmpfsにファイルが多すぎる場合、メモリの多くを占有している可能性があります:-)。 Shmemには グラフィックスメモリ割り当て を含めることもできますが、非常に大きくなる可能性があります。

MemAvailableには、意図的にスワップ可能なメモリは含まれていません。スワップしすぎると、長い遅延が発生する可能性があります。スワップ領域なしで実行することを選択したり、比較的限られた量だけを許可したりすることもできます。

MemAvailableの動作を再確認する必要がありました。一見すると、コードはこの違いについて言及していないようです。

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

ただし、Shmemを「使用済み」メモリとして正しく処理することがわかりました。 tmpfsに1GBのファイルをいくつか作成しました。 Shmemが1GB増えるごとにMemAvailableが1GBずつ減少します。したがって、「ファイルLRUリスト」のサイズには、共有メモリやその他のスワップ可能なメモリは含まれません。 (これらの同じページ数も使用されていることに気づきました 「ダーティリミット」を計算するコードで )。

このMemAvailableの計算では、カーネルの「最低水準点」と同等の少なくとも十分なファイルキャッシュを保持する必要があることも想定しています。または現在のキャッシュの半分-どちらか小さい方。 (これは、再生可能なスラブについても同じ前提です)。カーネルの「最低水準点」は調整できますが、通常は システムRAMの約2% です。したがって、大まかな見積もりだけが必要な場合は、この部分を無視できます:-)。

約100MBのプログラムコードをページキャッシュにマップしてfirefoxを実行している場合、通常はその100MBをRAM :-)に保持する必要があります。そうしないと、せいぜい遅延が発生し、最悪の場合、システムはすべての時間を費やします スラッシング 異なるアプリケーション間で。したがって、MemAvailableはRAMの一部を許可しています。十分に許可されないか、過度に寛大になる可能性があります。「これらの要因の影響はシステムによって異なりますシステムに」。

多くのPCワークロードでは、「大量のファイル」に関するポイントは重要ではありません。それでも、ラップトップには現在、8 MBのRAMのうち500 MBの再利用可能なスラブメモリがあります。これは、ext4_inode_cache(300Kを超えるオブジェクト)が原因です。最近、ファイルシステム全体をスキャンして、自分のディスク領域を使用しているものを見つける必要があったためです。コマンドdf -x / | sort -nを使用しましたが、 Gnome Disk Usage Analyzerも同じことを行います。

2. [編集]コントロールグループのメモリ

いわゆる「Linuxコンテナ」は、namespacescgroups、および好みに応じて他のさまざまな機能から構築されます:-)。彼らは、ほぼ完全なLinuxシステムのようなものを実行するのに十分な説得力のある環境を提供するかもしれません。ホスティングサービスは、このようなコンテナーを構築し、「仮想サーバー」として販売することができます:-)。

ホスティングサーバーは、メインラインLinuxにない機能を使用して「仮想サーバー」を構築することもできます。 OpenVZ コンテナーは、メインラインのcgroupよりも2年前に作成され、「beancounters」を使用してメモリを制限する場合があります。したがって、ドキュメントを読んだり、メインラインのLinuxカーネルについて質問したりするだけでは、これらのメモリ制限がどのように機能するかを正確に理解できません。 cat /proc/user_beancounters は、現在の使用状況と制限を示します。 vzubc は、少しわかりやすい形式で表示します。 beancountersのメインページ は行名を文書化します。

制御グループには、その内部のプロセスにメモリ制限を設定する機能が含まれています。そのようなcgroup内でアプリケーションを実行する場合、システムメモリのすべてがアプリケーションで使用できるわけではありません:-)。では、この場合、どのようにして使用可能なメモリを確認できますか?

cgroup-v1 を使用するか cgroup-v2 を使用するかによって、このインターフェースはさまざまな点で異なります。

私のラップトップのインストールではcgroup-v1を使用しています。 cat /sys/fs/cgroup/memory/memory.statを実行できます。ファイルには、total_rsstotal_cachetotal_shmemなどのさまざまなフィールドが表示されます。 tmpfsを含むshmemは、メモリ制限にカウントされます。 total_rssMemFreeの逆の等価物として見ることができると思います。また、スラブを含むカーネルメモリを表すmemory.kmem.usage_in_bytesファイルもあります。 (memory.kmem.にはmemory.kmem.tcp.と将来の拡張機能も含まれていると思いますが、これは明示的に文書化されていません)。再利用可能なスラブメモリを表示するための個別のカウンターはありません。 cgroup-v1のドキュメントによると、メモリ制限に達してもしないと、スラブメモリの再利用はトリガーされません。 (このドキュメントには「絶望的に古くなっている」という免責事項があり、現在のソースコードを確認する必要があります)。

cgroup-v2は異なります。ルート(トップレベル)cgroupはメモリアカウンティングをサポートしていないと思います。 cgroup-v2にはまだmemory.statファイルがあります。すべてのフィールドは子cgroup全体で合計されるため、total_...フィールドを探す必要はありません。 fileフィールドがあり、これはcacheと同じことを意味します。厄介なことに、memory.statの中にrssのような全体的なフィールドが表示されません。個別のフィールドを合計する必要があると思います。再利用可能なスラブメモリと再利用不可能なスラブメモリには別々の統計があります。 v2 cgroupは、メモリが不足し始めたときにスラブを再利用するように設計されていると思います。

Linux cgroupは/proc/meminfo(または/proc内の他のファイル)を自動的に仮想化しないため、マシン全体の値が表示されます。これはVPSの顧客を混乱させます。ただし、名前空間を使用して/proc/meminfoをファイルに置き換えることは可能です 特定のコンテナーソフトウェアによって偽装 。偽の値がどれほど役立つかは、特定のソフトウェアが何をするかによって異なります。

systemdは、cgroup-v1を安全に委任できないと考えています。コンテナに。私はcgroup-v1システムのsystemd-nspawnコンテナー内を調べました。内部に配置されたcgroupと、そのメモリアカウンティングを確認できます。一方、含まれているsystemdは、リソースアカウンティング用の通常のサービスごとのcgroupを設定しません。このcgroup内でメモリアカウンティングが有効になっていない場合は、コンテナーがそれを有効にできないと思います。

私がcgroup-v2コンテナー内にいる場合、それは実際のcgroup-v2システムのルートとは異なって見え、そのトップレベルのcgroupのメモリアカウンティングを見ることができると思います。または、表示できるcgroupでメモリアカウンティングが有効になっていない場合は、許可が委任されて systemdでメモリアカウンティングを有効にする (または同等のもの)が許可されます。

10
sourcejedi