Voglio fare alcuni test a basso consumo e per questo ho bisogno di avere il 90% della memoria libera piena.
Come posso farlo su un *nix
sistema?
Voglio fare alcuni test a basso consumo e per questo ho bisogno di avere il 90% della memoria libera piena.
Come posso farlo su un *nix
sistema?
Risposte:
stress-ng è un generatore di carichi di lavoro che simula lo stress cpu / mem / io / hdd sui sistemi POSIX. Questa chiamata dovrebbe fare il trucco su Linux <3.14:
stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Per Linux> = 3.14, è possibile utilizzare MemAvailable
invece per stimare la memoria disponibile per i nuovi processi senza scambiare:
stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Adatta la /proc/meminfo
chiamata con free(1)
/ vm_stat(1)
/ etc. se ne hai bisogno portatile.
stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
--vm 1 and --vm-keep
sono molto importanti. Semplicemente --vm-bytes
non fa nulla e potresti essere indotto a pensare di poter allocare tutta la memoria di cui hai bisogno / desideri. Ho avuto un po 'di questo fino a quando ho provato a controllare la sanità mentale assegnando 256 G di memoria. Questo non è un difetto nella risposta, fornisce i flag corretti, solo un'ulteriore attenzione.
-m 1
. Secondo la manpage dello stress, -m N
è l'abbreviazione di --vm N
: spawn N
lavoratori che ruotano sumalloc()/free()
È possibile scrivere un programma C malloc()
nella memoria richiesta e quindi utilizzarlo mlock()
per impedire lo scambio della memoria.
Quindi, lascia che il programma attenda l'immissione da tastiera e sblocca la memoria, libera la memoria ed esce.
calloc
si imbatterà nello stesso problema IIRC. Tutta la memoria punterà solo alla stessa pagina azzerata di sola lettura. In realtà non verrà assegnato fino a quando non si tenta di scrivergli (che non funzionerà poiché è di sola lettura). L'unico modo per essere veramente sicuro che io sappia è di fare un memset
intero buffer. Vedere la seguente risposta per ulteriori informazioni stackoverflow.com/a/2688522/713554
Suggerirei di eseguire una VM con memoria limitata e testare il software in questo sarebbe un test più efficiente rispetto al tentativo di riempire la memoria sul computer host.
Questo metodo ha anche il vantaggio che se la situazione di memoria insufficiente causa errori OOM altrove e si blocca l'intero sistema operativo, si blocca solo la macchina virtuale che si sta testando non sulla macchina su cui si potrebbero avere altri processi utili in esecuzione.
Inoltre, se il test non è intensivo per CPU o I / O, è possibile eseguire contemporaneamente istanze dei test su una famiglia di macchine virtuali con una varietà di dimensioni di memoria ridotte.
Da questo commento HN: https://news.ycombinator.com/item?id=6695581
Basta riempire / dev / shm via dd o simili.
swapoff -a dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
pv
installato, aiuta a vedere il conteggio:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Se si dispone di strumenti GNU di base ( sh
, grep
, yes
e head
) si può fare questo:
yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily
Questo perché grep carica l'intera riga di dati nella RAM (l'ho imparato in modo piuttosto sfortunato quando si esegue il grepping di un'immagine del disco). La linea, generato da yes
, a capo sostituzione, sarà infinitamente lungo, ma è limitata dal head
per $BYTES
byte, così grep caricherà $ BYTE in memoria. Grep stesso usa come 100-200 KB per me, potrebbe essere necessario sottrarlo per un importo più preciso.
Se vuoi aggiungere anche un vincolo temporale, questo può essere fatto abbastanza facilmente in bash
(non funzionerà sh
):
cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n
La <(command)
cosa sembra essere poco conosciuta ma è spesso estremamente utile, maggiori informazioni qui: http://tldp.org/LDP/abs/html/process-sub.html
Quindi per l'uso di cat
: cat
attenderà il completamento degli input fino all'uscita e, mantenendo uno dei tubi aperti, manterrà vivo grep.
Se hai pv
e vuoi aumentare lentamente l'uso della RAM:
yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n
Per esempio:
yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n
Utilizzerà fino a un gigabyte a una velocità di 1 MB al secondo. Come bonus aggiuntivo, pv
ti mostrerà l'attuale tasso di utilizzo e l'utilizzo totale finora. Naturalmente questo può essere fatto anche con varianti precedenti:
yes | tr \\n x | head -c $BYTES | pv | grep n
Basta inserire la | pv |
parte per mostrare lo stato corrente (throughput e totale, per impostazione predefinita, penso - altrimenti vedi la pagina man (annuale)).
Perché un'altra risposta? La risposta accettata raccomanda l'installazione di un pacchetto (scommetto che c'è un rilascio per ogni chipset senza bisogno di un gestore di pacchetti); la risposta più votata raccomanda di compilare un programma C (non avevo un compilatore o una toolchain installati per compilare per la tua piattaforma di destinazione); la seconda risposta più votata consiglia di eseguire l'applicazione in una macchina virtuale (sì, lasciami semplicemente ddcard interna di questo telefono su USB o qualcosa del genere e crea un'immagine di virtualbox); il terzo suggerisce di modificare qualcosa nella sequenza di avvio che non riempie la RAM come desiderato; il quarto funziona solo nella misura in cui esiste il mountpoint / dev / shm (1) e (2) è grande (rimontaggio necessita root); il quinto combina molti dei precedenti senza codice di esempio; la sesta è un'ottima risposta ma non ho visto questa risposta prima di venire con il mio approccio, quindi ho pensato di aggiungere il mio, anche perché è più breve da ricordare o digitare se non vedi che la linea memblob è in realtà il nocciolo della questione; il settimo di nuovo non risponde alla domanda (usa invece ulimit per limitare un processo); l'ottavo tenta di farti installare python; il nono pensa che siamo tutti molto poco creativi e infine il decimo ha scritto il suo programma C ++ che causa lo stesso problema della risposta più votata.
set -e
, quindi ho appena imparato qualcosa :)
time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n
(usa una memoria da 10 GiB) richiede 1 minuto e 46 secondi. L'esecuzione del programma eatmemory di julman99 su github.com/julman99/eatmemory richiede 6 secondi. ... Bene, oltre al tempo di download e compilazione, ma è stato compilato senza problemi ... e molto rapidamente ... sul mio computer RHEL6.4. Comunque, mi piace questa soluzione. Perché reinventare la ruota?
Tengo una funzione per fare qualcosa di simile nei miei dotfile. 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
}
Quanto conta una semplice soluzione 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
e inoltre impostare vm.min_free_kbytes su un piccolo numero, forse 1024. Non l'ho provato, ma i documenti dicono che è così che controlli la rapidità dello scambio ... dovresti essere in grado di renderlo piuttosto lento, al punto da causare una condizione OOM sulla tua macchina. Vedi kernel.org/doc/Documentation/sysctl/vm.txt e kernel.org/doc/gorman/html/understand/understand005.html
Che ne dici di ramfs se esiste? Montarlo e copiarlo su un file di grandi dimensioni? Se non ci sono /dev/shm
e non ci sono ramfs - immagino un piccolo programma C che fa un grosso malloc basato su un valore di input? Potrebbe essere necessario eseguirlo più volte contemporaneamente su un sistema a 32 bit con molta memoria.
Se si desidera testare un determinato processo con memoria limitata, è possibile utilizzare meglio ulimit
per limitare la quantità di memoria allocabile.
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.
Penso che questo sia il caso di porre la domanda sbagliata e il buonsenso venga soffocato dalle persone in competizione per la risposta più creativa. Se devi solo simulare le condizioni OOM, non è necessario riempire la memoria. Basta usare un allocatore personalizzato e farlo fallire dopo un certo numero di allocazioni. Questo approccio sembra funzionare abbastanza bene per SQLite .
Ho scritto questo piccolo programma C ++ per questo: https://github.com/rmetzger/dynamic-ballooner
Il vantaggio di questa implementazione è che controlla periodicamente se deve liberare o riassegnare memoria.