MemAvailable
je součástí /proc/meminfo
od verze 3.14 jádra; bylo přidáno commitem 34e431b0a. To je určující faktor ve výstupních variacích, které ukazujete. Zpráva odevzdání uvádí, jak odhadnout dostupnou paměť bez MemAvailable
:
V současné době lze velikost paměti, která je k dispozici pro novou zátěž, aniž by bylo nutné systém přepínat do swapu, odhadnout z
MemFree
,Active(file)
,Inactive(file)
aSReclaimable
, stejně jako "nízké" vodoznaky z/proc/zoneinfo
.
Nízké vodoznaky jsou úrovní, pod kterou systém zamění. Takže při absenci MemAvailable
můžete alespoň sečíst hodnoty dané pro MemFree
, Active(file)
, Inactive(file)
a SReclaimable
(podle toho, které jsou uvedeny v /proc/meminfo
) a odečtěte spodní vodoznaky od /proc/zoneinfo
. Ten také uvádí počet bezplatných stránek na zónu, což může být užitečné pro srovnání...
Kompletní algoritmus je uveden v patchi meminfo.c
a zdá se, že je poměrně snadné se přizpůsobit:
- sečíst nízké vodoznaky ve všech zónách;
- vezměte identifikovanou volnou paměť (
MemFree
); - odečtěte nízký vodoznak (nemusíme se ho dotýkat, aby nedošlo k záměně);
- přidejte množství paměti, kterou můžeme použít z mezipaměti stránky (součet
Active(file)
aInactive(file)
):to je množství paměti, kterou využívá mezipaměť stránky, mínus buď polovina mezipaměti stránky, nebo nízký vodoznak, podle toho, která hodnota je menší; - přidejte množství paměti, kterou můžeme získat zpět (
SReclaimable
), podle stejného algoritmu.
Takže, když to všechno dáte dohromady, můžete získat paměť dostupnou pro nový proces pomocí:
awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') \
'{a[$1]=$2}
END{
print a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]-(12*low);
}' /proc/meminfo
I když je Stephenova odpověď naprosto dostačující a mýlí se na straně opatrnosti, rozhodl jsem se sepsat plnou logiku včetně minimálních srovnání. Informace se nejprve přečtou z /proc/meminfo a uloží se do proměnné, aby byly detaily paměti konzistentní.
LOW_WATERMARK=$(awk '$1 == "low" {LOW_WATERMARK += $2} END {print LOW_WATERMARK * 4096}' /proc/zoneinfo)
MEMINFO=$(</proc/meminfo)
MEMINFO_MEMFREE=$(echo "${MEMINFO}" | awk '$1 == "MemFree:" {print $2 * 1024}')
MEMINFO_FILE=$(echo "${MEMINFO}" | awk '{MEMINFO[$1]=$2} END {print (MEMINFO["Active(file):"] + MEMINFO["Inactive(file):"]) * 1024}')
MEMINFO_SRECLAIMABLE=$(echo "${MEMINFO}" | awk '$1 == "SReclaimable:" {print $2 * 1024}')
MEMINFO_MEMAVAILABLE=$((
MEMINFO_MEMFREE - LOW_WATERMARK
+ MEMINFO_FILE - ((MEMINFO_FILE/2) < LOW_WATERMARK ? (MEMINFO_FILE/2) : LOW_WATERMARK)
+ MEMINFO_SRECLAIMABLE - ((MEMINFO_SRECLAIMABLE/2) < LOW_WATERMARK ? (MEMINFO_SRECLAIMABLE/2) : LOW_WATERMARK)
))
if [[ "${MEMINFO_MEMAVAILABLE}" -le 0 ]]
then
MEMINFO_MEMAVAILABLE=0
fi
Výsledek uložený v proměnné je v bajtech.