Come riempire il 90% della memoria libera?


181

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 *nixsistema?


3
Deve davvero funzionare su qualsiasi sistema * nix?
un CVn

31
Invece di riempire la memoria, potresti invece creare una VM (usando docker, o vagabondo o qualcosa di simile) che abbia una quantità limitata di memoria?
abendigo,

4
@abendigo Per un QA molte delle soluzioni presentate qui sono utili: per un sistema operativo generico senza una piattaforma specifica i parametri di avvio della VM o del kernel potrebbero essere utili, ma per un sistema incorporato in cui si conoscono le specifiche di memoria del sistema di destinazione vorrei andare per il riempimento della memoria libera.
Eduard Florinescu,

2
Nel caso in cui qualcun altro sia un po 'scioccato dal punteggio qui: meta.unix.stackexchange.com/questions/1513/… ?
Riccioli d'oro

Risposte:


157

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 MemAvailableinvece 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/meminfochiamata con free(1)/ vm_stat(1)/ etc. se ne hai bisogno portatile.


3
stress --vm-bytes $ (awk '/ MemFree / {printf "% d \ n", $ 2 * 0,097;}' </ proc / meminfo) k --vm-keep -m 10
Robert,

1
La maggior parte di MemFree è gestita dal sistema operativo, quindi ho usato MemAvailable. Questo mi ha dato un utilizzo del 92% su Cent OS 7.stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
kujiy

buono a sapersi, MemAvailable è stato aggiunto a "stima di quanta memoria è disponibile per l'avvio di nuove applicazioni, senza scambio", vedere git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ ... e git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/…
tkrennwa

1
Proprio come una nota aggiunta, fornendo entrambi --vm 1 and --vm-keepsono molto importanti. Semplicemente --vm-bytesnon 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.
Sfogliando il

Questo è il motivo per cui c'è -m 1. Secondo la manpage dello stress, -m Nè l'abbreviazione di --vm N: spawn Nlavoratori che ruotano sumalloc()/free()
tkrennwa il

92

È 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.


25
Molto tempo fa ho dovuto testare un caso d'uso simile. Ho osservato che fino a quando non scrivi qualcosa in quella memoria non verrà effettivamente allocato (cioè fino a quando si verifica un errore di pagina). Non sono sicuro che mlock () se ne occupi.
Poorna,

2
Concordo con @siri; tuttavia, dipende dalla variante UNIX in uso.
Anthony,

2
Qualche ispirazione per il codice. Inoltre, penso che non sia necessario sbloccare / liberare la memoria . Il sistema operativo lo farà per te al termine del processo.
Sebastian

9
Probabilmente devi effettivamente scrivere nella memoria, il kernel potrebbe semplicemente sovraccaricare se lo mali. Se configurato su, ad es. Linux farà tornare correttamente malloc senza avere effettivamente la memoria libera e allocare effettivamente la memoria solo quando viene scritta. Vedi win.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen

7
@Sebastian: callocsi 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 memsetintero buffer. Vedere la seguente risposta per ulteriori informazioni stackoverflow.com/a/2688522/713554
Leo,

45

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.


31

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

8
Non tutti i * nix hanno / dev / shm. Qualche idea più portatile?
Tadeusz A. Kadłubowski l'

Se pvinstallato, aiuta a vedere il conteggio:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Otheus

1
Se vuoi la velocità, questo metodo è la scelta giusta! Perché alloca la quantità desiderata di RAM in pochi secondi. Non inoltrare su / dev / urandom, utilizzerà il 100% della CPU e impiegherà diversi minuti se la tua RAM è grande. ANCORA, / dev / shm ha una dimensione relativa nelle moderne distribuzioni Ubuntu / Debian, ha una dimensione predefinita al 50% della RAM fisica. Spero che possiate rimontare / dev / shm o magari creare un nuovo mount point. Assicurati solo che abbia le dimensioni effettive che desideri allocare.
DevelCuy

30
  1. eseguire linux;
  2. avvio con mem=nn[KMG]il parametro di avvio del kernel

(guarda in linux / Documentation / kernel-parameter.txt per i dettagli).


24

Se si dispone di strumenti GNU di base ( sh, grep, yese 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 headper $BYTESbyte, 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: catattenderà il completamento degli input fino all'uscita e, mantenendo uno dei tubi aperti, manterrà vivo grep.

Se hai pve 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, pvti 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.


soluzione adorabile. L'unico inconveniente è che il codice di uscita del costrutto è 1 perché grep non trova una corrispondenza. Nessuna delle soluzioni di stackoverflow.com/questions/6550484/… sembra risolverlo.
Holger Brandl,

@HolgerBrandl Un buon punto, non saprei come risolverlo. Questa è la prima volta che ne ho sentito parlare set -e, quindi ho appena imparato qualcosa :)
Luc

$ SECONDS non sembra una buona scelta poiché è una variabile incorporata che riflette il tempo trascorso dall'avvio della shell. vedi tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl

@HolgerBrandl Buona cattura, non lo sapevo. Un po 'bello trovare un terminale che è aperto per> 3 milioni di secondi attualmente: D. Ho aggiornato il post.
Luc,

Tecnica interessante! 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?
Mike S

18

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
}

1
Questa è la soluzione più bella di IMHO, poiché essenzialmente ha solo bisogno di funzionare, tutte le altre cose possono essere aggirate in qualsiasi shell. Si noti che in realtà rivendica il doppio della memoria rispetto ai dati dd prodotti, almeno temporaneamente. Testato su Debian 9, trattino 0,5,8-2,4. Se usi bash per eseguire la parte MEMBLOB, diventa molto lento e utilizza quattro volte la quantità prodotta da dd.
P.Péter,

16

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)

7
Ciò verrà probabilmente sostituito rapidamente, con un impatto reale molto ridotto sulla pressione della memoria (a meno che non si riempia anche tutto lo scambio, che richiederà un po 'di tempo, di solito)
Joachim Sauer

1
Perché un unix dovrebbe essere scambiato mentre è disponibile la RAM? Questo è in realtà un modo plausibile per eliminare la cache del disco quando necessario.
Alexander Shcheblikin, l'

@AlexanderShcheblikin Questa domanda non riguarda lo sfratto della cache del disco (che è utile per il test delle prestazioni ma non per il test delle risorse limitate).
Gilles,

1
Questa soluzione ha funzionato per mettere insieme un paio di Gig nei miei test, anche se non ho provato a stressare la mia memoria. Ma, @JoachimSauer, uno potrebbe impostare sysctl vm.swappiness=0e 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
Mike S

semplicemente una riga per 1 GB: python -c "x = (1 * 1024 * 1024 * 1024/8) * (0,); raw_input ()"
adrianlzt

10

Che ne dici di ramfs se esiste? Montarlo e copiarlo su un file di grandi dimensioni? Se non ci sono /dev/shme 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.


8

Se si desidera testare un determinato processo con memoria limitata, è possibile utilizzare meglio ulimitper limitare la quantità di memoria allocabile.


2
In realtà questo non funziona su Linux (non so per altri * nix). 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.
Patrick,

4

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 .


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.