Je veux faire un peu test de faibles ressources et pour cela j'ai besoin d'avoir 90% de la mémoire libre pleine.
Comment puis-je le faire sur un *nix
système?
stress-ng est un générateur de charge de travail qui simule le stress des processeurs/mem/io/hdd sur les systèmes POSIX. Cet appel devrait faire l'affaire sous Linux <3.14:
stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Pour Linux> = 3.14, vous pouvez utiliser MemAvailable
à la place pour estimer la mémoire disponible pour les nouveaux processus sans permuter:
stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Adaptez l'appel /proc/meminfo
Avec free(1)
/vm_stat(1)
/etc. si vous en avez besoin portable.
Vous pouvez écrire un programme C dans malloc()
la mémoire requise, puis utiliser mlock()
pour empêcher la mémoire d'être permutée.
Ensuite, laissez simplement le programme attendre la saisie au clavier, déverrouillez la mémoire, libérez-la et quittez.
Je suggère d'exécuter un VM avec une mémoire limitée et de tester le logiciel dans ce qui serait un test plus efficace que d'essayer de remplir la mémoire sur la machine hôte.
Cette méthode a également l'avantage que si la situation de mémoire insuffisante provoque des erreurs OOM ailleurs et bloque l'ensemble du système d'exploitation, vous ne suspendez que le VM que vous testez dans votre machine et que vous pourriez avoir d'autres processus utiles en cours d'exécution.
De plus, si vos tests ne sont pas CPU ou IO intensif, vous pouvez exécuter simultanément des instances des tests sur une famille de machines virtuelles avec une variété de tailles de mémoire faibles.
De ce commentaire HN: https://news.ycombinator.com/item?id=6695581
Remplissez simplement/dev/shm via dd ou similaire.
swapoff -a dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
Si vous avez des outils de base GNU (sh
, grep
, yes
et head
), vous pouvez le faire:
yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily
Cela fonctionne parce que grep charge toute la ligne de données dans RAM (j'ai appris cela d'une manière plutôt malheureuse lors de la réception d'une image disque). La ligne, générée par yes
, remplaçant les sauts de ligne seront infiniment longs, mais sont limités par head
à $BYTES
octets, donc grep chargera $ BYTES en mémoire. Grep lui-même utilise comme 100-200 Ko pour moi, vous devrez peut-être soustraire cela pour un montant plus précis.
Si vous souhaitez également ajouter une contrainte de temps, cela peut être fait assez facilement dans bash
(ne fonctionnera pas dans sh
):
cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n
La chose <(command)
semble être peu connue mais est souvent extrêmement utile, plus d'informations ici: http://tldp.org/LDP/abs/html/process-sub.html
Ensuite, pour l'utilisation de cat
: cat
attendra la fin des entrées jusqu'à la fermeture, et en gardant l'un des canaux ouverts, il gardera grep en vie.
Si vous avez pv
et que vous souhaitez augmenter lentement RAM utilisez:
yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n
Par exemple:
yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n
Utilisera jusqu'à un gigaoctet à un taux de 1 Mo par seconde. En prime, pv
vous montrera le taux d'utilisation actuel et l'utilisation totale jusqu'à présent. Bien sûr, cela peut également être fait avec les variantes précédentes:
yes | tr \\n x | head -c $BYTES | pv | grep n
Il suffit d'insérer la partie | pv |
Pour vous montrer l'état actuel (débit et total, par défaut, je pense - sinon voir la page man (ual)).
Pourquoi une autre réponse? La réponse acceptée recommande d'installer un package (je parie qu'il existe une version pour chaque chipset sans avoir besoin d'un gestionnaire de packages); la réponse la plus votée recommande de compiler un programme C (je n'ai pas installé de compilateur ou de chaîne d'outils pour compiler pour votre plate-forme cible); la deuxième réponse la plus votée recommande d'exécuter l'application dans un VM (ouais permettez-moi de simplement dd la carte SD interne de ce téléphone sur USB ou quelque chose et créer une image de virtualbox); le troisième suggère de modifier quelque chose dans le démarrage séquence qui ne remplit pas le RAM comme souhaité; le quatrième ne fonctionne que dans la mesure où le point de montage/dev/shm (1) existe et (2) est grand (le remontage nécessite la racine); le cinquième combine bon nombre des éléments ci-dessus sans exemple de code; le sixième est une excellente réponse, mais je n'ai pas vu cette réponse avant de proposer ma propre approche, j'ai donc pensé ajouter la mienne, également parce qu'elle est plus courte à retenir ou à taper si vous ne voyez pas que la ligne memblob est en fait le nœud du problème; le septième ne répond pas à la question (utilise ulimit pour limiter un processus à la place); le huitième essaie de vous faire installer python; le neuvième pense que nous sont tous très peu créatifs et finalement le dixième a écrit son propre programme C++ qui provoque le même problème que la réponse la plus votée.
mem=nn[KMG]
paramètre de démarrage du noyau(regardez dans linux/Documentation/kernel-parameters.txt pour plus de détails).
Je garde une fonction pour faire quelque chose de similaire dans mes fichiers dot. 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
}
Que diriez-vous d'une simple solution 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)
Que diriez-vous de ramfs s'il existe? Le monter et copier sur un gros fichier? S'il n'y a pas de /dev/shm
et pas de ramfs - je suppose qu'un petit programme C qui fait un grand malloc basé sur une valeur d'entrée? Pourrait avoir à l'exécuter plusieurs fois à la fois sur un système 32 bits avec beaucoup de mémoire.
Si vous souhaitez tester un processus particulier avec une mémoire limitée, il vaut mieux utiliser ulimit
pour restreindre la quantité de mémoire allouable.
Je pense qu'il s'agit de poser la mauvaise question et la mauvaise raison d'être noyé par des personnes en compétition pour la réponse la plus créative. Si vous avez seulement besoin de simuler des conditions de MOO, vous n'avez pas besoin de remplir la mémoire. Utilisez simplement un allocateur personnalisé et faites-le échouer après un certain nombre d'allocations. Cette approche semble fonctionner assez bien pour SQLite .
J'ai écrit ce petit programme C++ pour ça: https://github.com/rmetzger/dynamic-ballooner
L'avantage de cette implémentation est qu'elle vérifie périodiquement si elle a besoin de libérer ou de réallouer de la mémoire.