UPOZORNĚNÍ: Tuto opravu nepoužívejte, pokud máte povolenou swap, protože dva uživatelé hlásili horší efekty. Tento patch jsem testoval pouze se zakázaným swapem v jádře! (tj. CONFIG_SWAP není nastaven)
Dokud nebude další upozornění (nebo někdo nepřijde s něčím lepším), používám (a funguje to, pro mě) následující patch, abych se vyhnul jakémukoli rozbití disku / zamrznutí operačního systému, když dojde k nedostatku paměti, a tím i OOM-killeru spustí se co nejdříve (max 1 s):
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;
}
Bohužel výše uvedené karty převedly na mezery, takže pokud chcete nezpracovaný patch, je zde.
Tato oprava nevylučuje Active(file)
stránky pod tlakem paměti, a tedy nezpůsobí kswapd0
(ale vidět v iotop
jako každý program sám) znovu načíst spustitelné stránky každého běžícího procesu pokaždé, když dojde k přepnutí kontextu, aby bylo možné programu (pokračovat) spuštění. Vyhnete se tak spoustě disků a operační systém nezamrzne.
Výše uvedené bylo testováno s jádrem 4.18.5 (a nyní testováním 4.18.7) uvnitř dom0 Qubes OS 4.0 (Fedora 25) a všech virtuálních počítačů (Fedora 28), které používám.
Pro první verzi tohoto patche, který také funguje (zřejmě), viz EDIT
právě na otázku, na kterou je toto odpověď.
AKTUALIZACE: Po chvíli používání tohoto patche na notebooku ArchLinux s 16G RAM (minus 512M vyhrazených pro integrovanou grafickou kartu) a bez swapu (vypnuto i v jádře) mohu říci, že systému může dojít paměť dříve než bez le9d.patch (rev. 3), a tak se OOM-killer spouští pro Xorg nebo chromium nebo jiné, když by to bez patche nebylo. A tak jako zmírnění, zdá se, že to pro mě zatím funguje, jsem spouštěl echo 1 > /proc/sys/vm/drop_caches
kdykoli Active(file)
číslo v /proc/meminfo je přes 2G alias 2000000 KB (např. získejte počet KB pomocí tohoto kódu:grep 'Active(file):' /proc/meminfo|tr -d ' '|cut -f2 -d:|sed 's/kB//'
) a tuto kontrolu proveďte pomocí sleep 5
později. Ale v poslední době, abych zkompiloval firefox-hg v /tmp, což je tmpfs a které nakonec používá 12G a zajistilo se, že nebude zabito OOM, používám 500 000 místo 2 000 000 KB. Určitě je to lepší, než zmrazit celý systém (tj. když bez le9d.patch), což by se stalo v tomto případě kompilace firefox. Bez této kontroly Active(file)
nejde výše než 4G, ale to stačí k OOM-zabití Xorg, pokud něco chce více paměti, jako například v tomto případě kompilace firefox nebo dokonce při pouhém kopírování mnoha gigabajtů přes půlnoční velitele (pokud si to dobře pamatuji).
Pomoci by měl parametr memory.min v paměťovém řadiči cgroups-v2.
Dovolím si citovat:
"Ochrana pevné paměti. Pokud je využití paměti cgroup v rámci její efektivní minimální hranice, paměť cgroup nebude za žádných podmínek obnovena. Pokud není k dispozici žádná nechráněná regenerovatelná paměť, je vyvolán zabiják OOM."
https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
Chcete-li odpovědět na otázku, zde je jednoduchá/předběžná oprava, která nezabrání vystěhování Active(file)
(jak je vidět v /proc/meminfo
) pokud je to méně než 256 MiB, zdá se, že to funguje dobře (žádné lámání disku) s 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;
}
Všimněte si, že některé zatím nebudou nalezeny regrese na jádře 5.3.0-rc4-gd45331b00ddb způsobí zamrznutí systému (bez rozbití disku a sysrq bude stále fungovat) i bez tohoto patche.
(jakýkoli nový vývoj související s tímto by se měl odehrát zde.)