MemAvailable
está incluido en /proc/meminfo
desde la versión 3.14 del kernel; fue agregado por el compromiso 34e431b0a. Ese es el factor determinante en las variaciones de salida que muestra. El mensaje de confirmación indica cómo estimar la memoria disponible sin MemAvailable
:
Actualmente, la cantidad de memoria que está disponible para una nueva carga de trabajo, sin forzar el intercambio del sistema, se puede estimar a partir de MemFree
, Active(file)
, Inactive(file)
y SReclaimable
, así como las marcas de agua "bajas" de /proc/zoneinfo
.
Las marcas de agua bajas son el nivel por debajo del cual se intercambiará el sistema. Entonces, en ausencia de MemAvailable
al menos puedes sumar los valores dados para MemFree
, Active(file)
, Inactive(file)
y SReclaimable
(lo que esté presente en /proc/meminfo
), y reste las marcas de agua bajas de /proc/zoneinfo
. Este último también enumera el número de páginas libres por zona, lo que podría ser útil como comparación...
El algoritmo completo se proporciona en el parche para meminfo.c
y parece razonablemente fácil de adaptar:
- sumar las marcas de agua bajas en todas las zonas;
- tomar la memoria libre identificada (
MemFree
); - restar la marca de agua baja (debemos evitar tocar eso para evitar el intercambio);
- agregue la cantidad de memoria que podemos usar desde el caché de la página (suma de
Active(file)
yInactive(file)
):esa es la cantidad de memoria utilizada por la memoria caché de la página, menos la mitad de la memoria caché de la página o la marca de agua baja, lo que sea menor; - añadir la cantidad de memoria que podemos reclamar (
SReclaimable
), siguiendo el mismo algoritmo.
Entonces, juntando todo esto, puede obtener la memoria disponible para un nuevo proceso con:
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
Si bien la respuesta de Stephen es perfectamente suficiente y se equivoca por precaución, decidí escribir la lógica completa, incluidas las comparaciones mínimas. La información se lee primero de /proc/meminfo y se almacena en una variable para que los detalles de la memoria sean coherentes.
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
El resultado almacenado en la variable está en bytes.