MemAvailable
ist in /proc/meminfo
enthalten ab Version 3.14 des Kernels; es wurde von Commit 34e431b0a hinzugefügt. Das ist der entscheidende Faktor für die von Ihnen gezeigten Ausgangsvariationen. Die Commit-Nachricht gibt an, wie der verfügbare Speicher ohne MemAvailable
geschätzt wird :
Derzeit kann die Menge an Arbeitsspeicher, die für eine neue Arbeitslast verfügbar ist, ohne das System in den Swap zu drängen, auf MemFree
geschätzt werden , Active(file)
, Inactive(file)
, und SReclaimable
, sowie die "niedrigen" Wasserzeichen von /proc/zoneinfo
.
Die niedrigen Wassermarken sind das Niveau, unterhalb dessen das System wechselt. Also ohne MemAvailable
Sie können zumindest die für MemFree
angegebenen Werte addieren , Active(file)
, Inactive(file)
und SReclaimable
(je nachdem, welche in /proc/meminfo
vorhanden sind ) und subtrahieren Sie die niedrigen Wasserzeichen von /proc/zoneinfo
. Letzteres listet auch die Anzahl der freien Seiten pro Zone auf, was als Vergleich nützlich sein könnte...
Der vollständige Algorithmus ist im Patch zu meminfo.c
angegeben und scheint einigermaßen einfach anzupassen:
- die niedrigen Wassermarken über alle Zonen summieren;
- Nehmen Sie den identifizierten freien Speicher (
MemFree
); - subtrahieren Sie das untere Wasserzeichen (wir müssen es vermeiden, es zu berühren, um ein Vertauschen zu vermeiden);
- Fügen Sie die Speichermenge hinzu, die wir aus dem Seitencache verwenden können (Summe von
Active(file)
undInactive(file)
):Das ist die vom Seiten-Cache verwendete Speichermenge abzüglich entweder der Hälfte des Seiten-Cache oder des unteren Wasserzeichens, je nachdem, welcher Wert kleiner ist; - Fügen Sie die Menge an Speicher hinzu, die wir zurückfordern können (
SReclaimable
), nach demselben Algorithmus.
Wenn Sie all dies zusammenfassen, können Sie den Speicher für einen neuen Prozess verfügbar machen mit:
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
Während Stephens Antwort vollkommen ausreichend ist und auf Nummer sicher geht, habe ich beschlossen, die vollständige Logik einschließlich der minimalen Vergleiche aufzuschreiben. Informationen werden zuerst aus /proc/meminfo gelesen und in einer Variablen gespeichert, damit Speicherdetails konsistent sind.
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
Das in der Variablen gespeicherte Ergebnis ist in Bytes angegeben.