Quiero hacer algunas pruebas de bajos recursos y para eso necesito tener el 90% de la memoria libre llena.
¿Cómo puedo hacer esto en un *nix
sistema?
Quiero hacer algunas pruebas de bajos recursos y para eso necesito tener el 90% de la memoria libre llena.
¿Cómo puedo hacer esto en un *nix
sistema?
Respuestas:
stress-ng es un generador de carga de trabajo que simula el estrés de cpu / mem / io / hdd en los sistemas POSIX. Esta llamada debería hacer el truco en Linux <3.14:
stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Para Linux> = 3.14, puede usar MemAvailable
en su lugar para estimar la memoria disponible para nuevos procesos sin intercambiar:
stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Adapte la /proc/meminfo
llamada con free(1)
/ vm_stat(1)
/ etc. Si lo necesitas portátil.
stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
--vm 1 and --vm-keep
es muy importante. Simplemente --vm-bytes
no hace nada y puede que lo engañen y piense que puede asignar tanta memoria como necesite / desee. Me mordió esto hasta que traté de comprobar mi cordura mediante la asignación de 256G de memoria. Esta no es una falla en la respuesta, proporciona los indicadores correctos, solo una precaución adicional.
-m 1
. De acuerdo con la página de manual de estrés, -m N
es la abreviatura de --vm N
: los N
trabajadores engendran girandomalloc()/free()
Puede escribir un programa en C en malloc()
la memoria requerida y luego usar mlock()
para evitar que la memoria se intercambie.
Luego, simplemente deje que el programa espere la entrada del teclado y desbloquee la memoria, libere la memoria y salga.
calloc
se encontrará con el mismo problema IIRC. Toda la memoria solo apuntará a la misma página puesta a cero de solo lectura. En realidad, no se asignará hasta que intente escribir en él (lo que no funcionará ya que es de solo lectura). La única forma de estar realmente seguro de que lo sé es hacer una parte memset
del búfer completo. Consulte la siguiente respuesta para obtener más información stackoverflow.com/a/2688522/713554
Sugeriría ejecutar una VM con memoria limitada y probar el software en eso sería una prueba más eficiente que tratar de llenar la memoria en la máquina host.
Ese método también tiene la ventaja de que si la situación de poca memoria causa errores OOM en otro lugar y bloquea todo el sistema operativo, solo bloquea la VM que está probando, no en su máquina, en la que podría tener otros procesos útiles ejecutándose.
Además, si sus pruebas no son intensivas en CPU o IO, puede ejecutar simultáneamente las pruebas en una familia de máquinas virtuales con una variedad de tamaños de memoria baja.
De este comentario de HN: https://news.ycombinator.com/item?id=6695581
Simplemente complete / dev / shm a través de dd o similar.
swapoff -a dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
pv
está instalado, es dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Si dispone de herramientas básicas de GNU ( sh
, grep
, yes
y head
) se puede hacer esto:
yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily
Esto funciona porque grep carga toda la línea de datos en RAM (aprendí esto de una manera bastante desafortunada cuando grep una imagen de disco). La línea, generada por yes
, reemplazando las nuevas líneas, será infinitamente larga, pero está limitada head
a $BYTES
bytes, por lo que grep cargará $ BYTES en la memoria. Grep en sí usa como 100-200KB para mí, es posible que deba restar eso para obtener una cantidad más precisa.
Si también desea agregar una restricción de tiempo, esto se puede hacer con bastante facilidad en bash
(no funcionará sh
):
cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n
La <(command)
cosa parece ser poco conocida, pero a menudo es extremadamente útil, más información aquí: http://tldp.org/LDP/abs/html/process-sub.html
Luego, para el uso de cat
: cat
esperará a que se completen las entradas hasta que salga, y al mantener abierta una de las tuberías, mantendrá vivo a grep.
Si tiene pv
y desea aumentar lentamente el uso de RAM:
yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n
Por ejemplo:
yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n
Utilizará hasta un gigabyte a una velocidad de 1 MB por segundo. Como una ventaja adicional, pv
le mostrará la tasa de uso actual y el uso total hasta el momento. Por supuesto, esto también se puede hacer con variantes anteriores:
yes | tr \\n x | head -c $BYTES | pv | grep n
Simplemente insertando la | pv |
parte le mostrará el estado actual (rendimiento y total, por defecto, creo; de lo contrario, vea la página man (ual)).
¿Por qué otra respuesta? La respuesta aceptada recomienda instalar un paquete (apuesto a que hay una versión para cada conjunto de chips sin necesidad de un administrador de paquetes); la respuesta más votada recomienda compilar un programa C (no tenía un compilador o una cadena de herramientas instalada para compilar para su plataforma de destino); la segunda respuesta más votada recomienda ejecutar la aplicación en una máquina virtual (sí, permítanme dd la tarjeta sd interna de este teléfono a través de usb o algo así y crear una imagen de caja virtual); el tercero sugiere modificar algo en la secuencia de arranque que no llena la RAM como se desea; el cuarto solo funciona en la medida en que existe / dev / shm mountpoint (1) y (2) es grande (el montaje necesita root); el quinto combina muchos de los anteriores sin código de muestra; la sexta es una gran respuesta, pero no vi esta respuesta antes de proponer mi propio enfoque, así que pensé en agregar el mío, también porque es más corto de recordar o escribir si no ves que la línea de memblob es realmente el quid de la cuestión; el séptimo nuevamente no responde la pregunta (en su lugar usa ulimit para limitar un proceso); el octavo intenta que instales python; el noveno piensa que todos somos muy poco creativos y finalmente el décimo escribió su propio programa C ++ que causa el mismo problema que la respuesta más votada.
set -e
, así que aprendí algo :)
time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n
(use memoria de 10 GiB) toma 1 minuto 46 segundos. Ejecutar el programa eatmemory de julman99 en github.com/julman99/eatmemory toma 6 segundos. ... Bueno, más el tiempo de descarga y compilación, pero se compiló sin problemas ... y muy rápidamente ... en mi máquina RHEL6.4. Aún así, me gusta esta solución. ¿Por qué reinventar la rueda?
Mantengo una función para hacer algo similar en mis archivos de puntos. https://github.com/sagotsky/.dotfiles/blob/master/.functions#L248
function malloc() {
if [[ $# -eq 0 || $1 -eq '-h' || $1 -lt 0 ]] ; then
echo -e "usage: malloc N\n\nAllocate N mb, wait, then release it."
else
N=$(free -m | grep Mem: | awk '{print int($2/10)}')
if [[ $N -gt $1 ]] ;then
N=$1
fi
sh -c "MEMBLOB=\$(dd if=/dev/urandom bs=1MB count=$N) ; sleep 1"
fi
}
¿Cómo abunda una solución simple de Python?
#!/usr/bin/env python
import sys
import time
if len(sys.argv) != 2:
print "usage: fillmem <number-of-megabytes>"
sys.exit()
count = int(sys.argv[1])
megabyte = (0,) * (1024 * 1024 / 8)
data = megabyte * count
while True:
time.sleep(1)
sysctl vm.swappiness=0
y, además, establecer vm.min_free_kbytes en un número pequeño, tal vez 1024. No lo he probado, pero los documentos dicen que así es como controlas la rapidez de intercambio ... deberías ser capaz de hacerlo bastante lento, hasta el punto de causar una condición OOM en su máquina. Ver kernel.org/doc/Documentation/sysctl/vm.txt y kernel.org/doc/gorman/html/understand/understand005.html
¿Qué tal ramfs si existe? ¿Montarlo y copiar sobre un archivo grande? Si no /dev/shm
hay ramfs y no hay ramfs, ¿supongo que un pequeño programa en C que hace un malloc grande basado en algún valor de entrada? Puede que tenga que ejecutarlo varias veces a la vez en un sistema de 32 bits con mucha memoria.
Si desea probar un proceso particular con memoria limitada, es mejor que utilice ulimit
para restringir la cantidad de memoria asignable.
man setrlimit
:RLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.
Creo que este es un caso de hacer la pregunta incorrecta y la cordura ahogada por las personas que compiten por la respuesta más creativa. Si solo necesita simular condiciones OOM, no necesita llenar memoria. Simplemente use un asignador personalizado y haga que falle después de un cierto número de asignaciones. Este enfoque parece funcionar lo suficientemente bien para SQLite .
Escribí este pequeño programa de C ++ para eso: https://github.com/rmetzger/dynamic-ballooner
La ventaja de esta implementación es que verifica periódicamente si necesita liberar o reasignar memoria.