警告: スワップを有効にしている場合は、このパッチを使用しないでください。2 人のユーザーがより悪い影響を報告しています。このパッチは、カーネルでスワップを無効にしてテストしただけです! (つまり、CONFIG_SWAP が設定されていません)
さらなる通知があるまで (または誰かがより良いものを思い付くまで)、メモリ不足を実行しようとしているときにディスクのスラッシング/OS のフリーズを回避するために、次のパッチを使用しています (そして、私にとっては機能します)。できるだけ早くトリガーします (最大 1 秒):
revision 3
preliminary patch to avoid disk thrashing (constant reading) under memory pressure before OOM-killer triggers
more info: https://gist.github.com/constantoverride/84eba764f487049ed642eb2111a20830
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 32699b2..7636498 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -208,7 +208,7 @@ enum lru_list {
#define for_each_lru(lru) for (lru = 0; lru < NR_LRU_LISTS; lru++)
-#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_ACTIVE_FILE; lru++)
+#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_INACTIVE_FILE; lru++)
static inline int is_file_lru(enum lru_list lru)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 03822f8..1f3ffb5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2086,9 +2086,9 @@ static unsigned long shrink_list(enum lr
struct scan_control *sc)
{
if (is_active_lru(lru)) {
- if (inactive_list_is_low(lruvec, is_file_lru(lru),
- memcg, sc, true))
- shrink_active_list(nr_to_scan, lruvec, sc, lru);
+ //if (inactive_list_is_low(lruvec, is_file_lru(lru),
+ // memcg, sc, true))
+ // shrink_active_list(nr_to_scan, lruvec, sc, lru);
return 0;
}
@@ -2234,7 +2234,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, MAX_NR_ZONES);
- file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
+ file = //lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES);
spin_lock_irq(&pgdat->lru_lock);
@@ -2345,7 +2345,7 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
sc->priority == DEF_PRIORITY);
blk_start_plug(&plug);
- while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
+ while (nr[LRU_INACTIVE_ANON] || //nr[LRU_ACTIVE_FILE] ||
nr[LRU_INACTIVE_FILE]) {
unsigned long nr_anon, nr_file, percentage;
unsigned long nr_scanned;
@@ -2372,7 +2372,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
* stop reclaiming one LRU and reduce the amount scanning
* proportional to the original scan target.
*/
- nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE];
+ nr_file = nr[LRU_INACTIVE_FILE] //+ nr[LRU_ACTIVE_FILE]
+ ;
nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON];
/*
@@ -2391,7 +2392,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
percentage = nr_anon * 100 / scan_target;
} else {
unsigned long scan_target = targets[LRU_INACTIVE_FILE] +
- targets[LRU_ACTIVE_FILE] + 1;
+ //targets[LRU_ACTIVE_FILE] +
+ 1;
lru = LRU_FILE;
percentage = nr_file * 100 / scan_target;
}
@@ -2409,10 +2411,12 @@ static void shrink_node_memcg(struct pgl
nr[lru] = targets[lru] * (100 - percentage) / 100;
nr[lru] -= min(nr[lru], nr_scanned);
+ if (LRU_FILE != lru) { //avoid this block for LRU_ACTIVE_FILE
lru += LRU_ACTIVE;
nr_scanned = targets[lru] - nr[lru];
nr[lru] = targets[lru] * (100 - percentage) / 100;
nr[lru] -= min(nr[lru], nr_scanned);
+ }
scan_adjusted = true;
}
残念ながら、上記はタブをスペースに変換したため、生のパッチが必要な場合はここにあります。
このパッチが行うことは、Active(file)
の削除ではありません ページがメモリ不足の状態にあるため、kswapd0
を引き起こさない (しかし iotop
で見られる 各プログラム自体として) 実行中のすべてのプロセスの実行可能ページを、コンテキストの切り替えがあるたびに再読み取りして、プログラムを (継続して) 実行できるようにします。したがって、大量のディスク スラッシングが回避され、OS がフリーズしてクロールすることはありません。
上記は、Qubes OS 4.0 の dom0(Fedora 25) および使用しているすべての VM (Fedora 28) 内のカーネル 4.18.5 (および現在は 4.18.7 をテスト中) でテストされています。
このパッチの最初のバージョンについては、(明らかに) 同様に機能します。EDIT
を参照してください。 これが答えであるまさにその質問について。
更新: このパッチを 16G RAM (統合グラフィックス カード用に予約されているマイナス 512M) の ArchLinux ラップトップでしばらく使用した後、システムは le9d.patch がない場合よりも早くメモリ不足になる可能性があると言えます。 (rev. 3)、したがって、OOM-killer は、パッチがなければ Xorg や chromium などの場合にトリガーされます。そして、軽減策として、これまでのところうまくいくようです。 echo 1 > /proc/sys/vm/drop_caches
を実行しています Active(file)
/proc/meminfo の数値が 2G を超えており、別名 2000000 KB です (例:このコードで KB 数を取得:grep 'Active(file):' /proc/meminfo|tr -d ' '|cut -f2 -d:|sed 's/kB//'
) sleep 5
でこのチェックを行います その後。しかし最近、tmpfs であり、最終的に 12G を使用する /tmp で firefox-hg をコンパイルし、OOM によって強制終了されないようにするために、2000000 KB ではなく 500000 を使用しています。これは、この firefox コンパイルの場合に発生するシステム全体のフリーズ (つまり、le9d.patch がない場合) よりも確実に優れています。このチェックがなければ、Active(file)
4Gを超えることはありませんが、このfirefoxコンパイルの場合や、真夜中のコマンダーを介して何ギガバイトもコピーする場合など、より多くのメモリが必要な場合は、XorgをOOMで殺すのに十分です(これを正しく覚えていれば)。
cgroups-v2 メモリ コントローラの memory.min パラメータが役立ちます。
つまり、引用させてください:
<ブロック引用>「ハード メモリ保護。cgroup のメモリ使用量が実効最小境界内にある場合、cgroup のメモリはどのような条件下でも再利用されません。保護されていない再利用可能なメモリが利用できない場合、OOM キラーが呼び出されます。」
https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
質問に答えるために、Active(file)
を削除しないための簡単な/予備的なパッチを次に示します。 (/proc/meminfo
で見られるように) ) 256 MiB 未満の場合、linux-stable 5.2.4 で問題なく (ディスクのスラッシングなしで) 動作するようです:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index dbdc46a84f63..7a0b7e32ff45 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2445,6 +2445,13 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
BUG();
}
+ if (NR_ACTIVE_FILE == lru) {
+ long long kib_active_file_now=global_node_page_state(NR_ACTIVE_FILE) * MAX_NR_ZONES;
+ if (kib_active_file_now <= 256*1024) {
+ nr[lru] = 0; //don't reclaim any Active(file) (see /proc/meminfo) if they are under 256MiB
+ continue;
+ }
+ }
*lru_pages += size;
nr[lru] = scan;
}
一部のまだ見つかっていないことに注意してください カーネル 5.3.0-rc4-gd45331b00ddb のリグレッションにより、このパッチがなくてもシステムがフリーズします (ディスクのスラッシングなしで、sysrq は引き続き動作します)。
(これに関連する新しい開発はここで行われるべきです。)