MemAvailable
est inclus dans /proc/meminfo
depuis la version 3.14 du noyau ; il a été ajouté par le commit 34e431b0a. C'est le facteur déterminant dans les variations de sortie que vous montrez. Le message de validation indique comment estimer la mémoire disponible sans MemAvailable
:
Actuellement, la quantité de mémoire disponible pour une nouvelle charge de travail, sans pousser le système en swap, peut être estimée à partir de
MemFree
,Active(file)
,Inactive(file)
, etSReclaimable
, ainsi que les filigranes "bas" de/proc/zoneinfo
.
Les filigranes bas sont le niveau en dessous duquel le système permutera. Donc en l'absence de MemAvailable
vous pouvez au moins additionner les valeurs données pour MemFree
, Active(file)
, Inactive(file)
et SReclaimable
(selon ceux qui sont présents dans /proc/meminfo
), et soustrayez les filigranes bas de /proc/zoneinfo
. Ce dernier répertorie également le nombre de pages libres par zone, ce qui peut être utile à titre de comparaison...
L'algorithme complet est donné dans le patch à meminfo.c
et semble assez facile à adapter :
- sumer les seuils bas dans toutes les zones ;
- prendre la mémoire libre identifiée (
MemFree
); - soustrayez le filigrane bas (nous devons éviter de le toucher pour éviter l'échange );
- ajoutez la quantité de mémoire que nous pouvons utiliser à partir du cache de la page (somme de
Active(file)
etInactive(file)
) :il s'agit de la quantité de mémoire utilisée par le cache de la page, moins la moitié du cache de la page ou le filigrane bas, selon le plus petit ; - ajouter la quantité de mémoire que nous pouvons récupérer (
SReclaimable
), suivant le même algorithme.
Ainsi, en mettant tout cela ensemble, vous pouvez obtenir la mémoire disponible pour un nouveau processus avec :
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
Alors que la réponse de Stephen est parfaitement suffisante et pécher par excès de prudence, j'ai décidé d'écrire la logique complète, y compris les comparaisons minimales. Les informations sont d'abord lues à partir de /proc/meminfo et stockées dans une variable afin que les détails de la mémoire soient cohérents.
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
Le résultat stocké dans la variable est en octets.