Linuxカーネルに特定の割合のメモリのみをバッファキャッシュに使用するように指示する方法はありますか?私は/proc/sys/vm/drop_caches
を使用してキャッシュを一時的にクリアできることを知っていますが、永続的に設定して、キャッシュがたとえばメインメモリの50%?
私がこれをしたい理由は、Ceph OSDを実行するサーバーがあり、ディスクから常にデータを提供し、数時間以内に物理メモリ全体をバッファーキャッシュとして使い切るためです。同時に、大量(数十GB)の物理メモリを割り当てるアプリケーションを実行する必要があります。一般的な考えに反して(バッファーキャッシュに関するほぼすべての質問に記載されているアドバイスを参照)、クリーンなキャッシュエントリを破棄してメモリを自動的に解放するのはnot瞬時:アプリケーションの起動に最大1分かかることがありますバッファキャッシュがいっぱいになると(*)、キャッシュをクリアした後(echo 3 > /proc/sys/vm/drop_caches
を使用)、同じアプリケーションがほぼ瞬時に起動します。
(*)起動時間のこの1分間、アプリケーションは新しいメモリで障害を起こしていますが、pageblock_pfn_to_page
という関数のVtuneによると、その時間の100%をカーネルで費やしています。この機能は、巨大なページを見つけるために必要なメモリの圧縮に関連しているようです。これにより、実際に断片化が問題であると思います。
絶対的な制限を必要とせず、カーネルにバッファをより速くフラッシュするように圧力をかける場合は、vm.vfs_cache_pressure
を確認する必要があります
この変数は、ページキャッシュとスワップではなく、VFSキャッシュのキャッシュに使用されるメモリを再利用するカーネルの傾向を制御します。この値を大きくすると、VFSキャッシュが再利用される率が高くなります。
範囲は0〜200です。圧力を上げるには、200の方向に動かします。デフォルトは100に設定されています。slabtop
コマンドを使用してメモリ使用量を分析することもできます。あなたの場合、dentry
と*_inode_cache
の値は高くなければなりません。
絶対的な制限が必要な場合は、cgroups
を調べる必要があります。 Ceph OSDサーバーをcgroup内に配置し、cgroupのmemory.limit_in_bytes
パラメーターを設定して、使用できる最大メモリを制限します。
memory.memsw.limit_in_bytes
は、メモリとスワップ使用量の合計の最大量を設定します。単位が指定されていない場合、値はバイトとして解釈されます。ただし、サフィックスを使用してより大きな単位を表すことができます。キロバイトの場合はkまたはK、メガバイトの場合はmまたはM、ギガバイトの場合はgまたはGです。
参照:
[1]- GlusterFS Linuxカーネルチューニング
[2]- RHEL 6リソース管理ガイド
A%についてはわかりませんが、時間制限を設定して、x分後にドロップすることができます。
最初にターミナルで
sync && echo 3 | Sudo tee /proc/sys/vm/drop_caches
現在のキャッシュをクリアします。
cron-job
にするAlt-F2を押し、gksudo gedit /etc/crontab
と入力します次に、この行を下部に追加します。
*/15 * * * * root sync && echo 3 > /proc/sys/vm/drop_caches
15分ごとにクリーニングします。最初のパラメーターを*/15ではなく*または*/5に変更して、本当に必要な場合は、1分または5分に設定できます。
キャッシュ以外の空きRAMを表示するには:
free -m | sed -n -e '3p' | grep -Po "\d+$
Ceph OSDが1つの独立したプロセスである場合、 cgroups を使用して、プロセスで使用されるリソースを制御できます。
メモリ制限付きのgroup1のような名前のcgroupを作成します(たとえば、50GBのCPUのような他の制限もサポートされています。例ではCPUも言及されています)。
cgcreate -g memory,cpu:group1
cgset -r memory.limit_in_bytes=$((50*1024*1024*1024)) group1
次に、アプリがすでに実行されている場合は、アプリをこのcgroupに追加します。
cgclassify -g memory,cpu:group1 $(pidof your_app_name)
または、このcgroup内でアプリを実行します。
cgexec -g memory,cpu:group1 your_app_name
質問の最後にあるあなたの直感は正しい方向に進んでいると思います。 CPU間でページを移行するA、NUMA対応のメモリ割り当て、またはB、おそらく、隣接する整列された領域を見つけようとする透明な巨大ページのデフラグコードのいずれかだと思います。
特定のワークロードでの著しいパフォーマンスの向上と、大きなメリットを提供せずに大量のCPU時間を消費する原因の両方について、ヒュージページとトランスペアレントヒュージページが確認されています。
実行しているカーネル、/ proc/meminfoの内容(または少なくともHugePages_ *の値)、そして可能であれば、pageblock_pfn_to_page()を参照するvtuneプロファイラーコールグラフの詳細を知っておくと役立ちます。
また、私の推測にふける場合は、次のコマンドでhugepageデフラグを無効にしてみてください。
echo 'never'>/sys/kernel/mm/transparent_hugepage/defrag
(カーネルによっては、代わりにこれになる場合があります:)
echo 'never'>/sys/kernel/mm/redhat_transparent_hugepage/defrag
最後に、このアプリは何十ギグのラムを使用していますか?何語?
「メモリページのフォールト」という用語を使用したので、設計と仮想メモリの操作に十分慣れていると思います。私は多くのI/Oを読み込まないほど攻撃的にフォールトする状況/アプリケーションを想像するのに苦労しています。ほとんどの場合、制限しようとしているバッファーキャッシュからです。
(興味があれば、MAP_ANONYMOUSやMAP_POPULATEなどのmmap(2)フラグと、実際にマップされた物理ページがある仮想ページを確認するために使用できるmincore(2)を確認してください。
幸運を!
tunedは、使用状況に応じてシステム設定を動的に調整する動的適応システム調整デーモンです。
$ man tuned
関連ドキュメントと構成ファイルを参照してください。
/etc/tuned
/etc/tuned/*.conf
/usr/share/doc/tuned-2.4.1
/usr/share/doc/tuned-2.4.1/TIPS.txt
This parameter may be useful for you.
** Set flushing to once per 5 minutes
** echo "3000" > /proc/sys/vm/dirty_writeback_centisecs
追加情報
syncコマンドは、バッファーをフラッシュします。つまり、未書き込みのすべてのデータを強制的にディスクに書き込み、すべてが安全に書き込まれていることを確認したい場合に使用できます。従来のUNIXシステムには、バックグラウンドでpdateと呼ばれるプログラムがあり、syncを30秒ごとに実行するため、通常は同期を使用する必要はありません。 Linuxには追加のデーモンbdflushがあります。これは、より不完全な同期をより頻繁に実行して、syncが原因となる重いディスクI/Oによる突然のフリーズを回避します。
Linuxでは、bdflushは更新によって開始されます。通常、心配する必要はありませんが、何らかの理由でbdflushが異常終了した場合、カーネルはこれについて警告します。手動で開始する必要があります(/ sbin/update)。