Je souhaite effectuer des tests avec peu de ressources et pour cela, je dois disposer de 90% de la mémoire libre.
Comment puis-je faire cela sur un *nix
système?
Je souhaite effectuer des tests avec peu de ressources et pour cela, je dois disposer de 90% de la mémoire libre.
Comment puis-je faire cela sur un *nix
système?
Réponses:
stress-ng est un générateur de charge de travail qui simule les contraintes CPU / 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 MemAvailable
plutôt utiliser l’ estimation de la mémoire disponible pour les nouveaux processus sans permutation:
stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1
Adapter l' /proc/meminfo
appel avec free(1)
/ vm_stat(1)
/ etc. si vous en avez besoin portable.
stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
--vm 1 and --vm-keep
sont très importants. Tout simplement --vm-bytes
ne fait rien et vous pourriez être induit en erreur en pensant que vous pouvez allouer autant de mémoire que vous avez besoin / envie. Je me suis laissé mordre par là jusqu'à ce que j'essaye de me vérifier en allouant 256G de mémoire. Ce n'est pas un défaut dans la réponse, il fournit les indicateurs corrects, juste un avertissement supplémentaire.
-m 1
. Selon la page de manuel stress, -m N
est l'abréviation de --vm N
: spawn N
workers spinning onmalloc()/free()
Vous pouvez écrire un programme C dans malloc()
la mémoire requise, puis l’utiliser mlock()
pour éviter que la mémoire ne soit remplacée.
Ensuite, laissez le programme attendre la saisie au clavier, déverrouillez la mémoire, libérez-la et quittez.
calloc
rencontrera le même problème IIRC. Toute la mémoire indiquera simplement la même page zéro en lecture seule. Il ne sera réellement alloué que lorsque vous aurez essayé d'écrire dessus (ce qui ne fonctionnera pas puisqu'il est en lecture seule). La seule façon d'être vraiment sûr que je sache est de faire un memset
tampon complet. Voir la réponse suivante pour plus d'informations stackoverflow.com/a/2688522/713554
Je suggérerais qu'exécuter une machine virtuelle avec une mémoire limitée et tester le logiciel serait un test plus efficace que d'essayer de remplir la mémoire sur la machine hôte.
Cette méthode présente également l’avantage que si la situation de mémoire insuffisante provoque des erreurs de MOO ailleurs et bloque tout le système d’exploitation, vous ne bloquez que la machine virtuelle que vous testez et non votre machine sur laquelle d’autres processus utiles pourraient s’exécuter.
De même, si vos tests ne nécessitent pas beaucoup de ressources processeur ou IO, vous pouvez simultanément exécuter des instances de tests sur une famille de machines virtuelles disposant de diverses tailles de mémoire.
De ce commentaire HN: https://news.ycombinator.com/item?id=6695581
Il suffit de remplir / dev / shm via dd ou similaire.
swapoff -a dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k
pv
est installé, il est utile de voir le compte:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
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 la totalité de la ligne de données dans la RAM (je l’ai appris d’une manière plutôt malheureuse lors de la récupération d’une image de disque). La ligne, générée par yes
, remplaçant les nouvelles lignes, sera infiniment longue, mais est limitée head
à $BYTES
octets, donc grep chargera $ BYTES en mémoire. Grep lui-même utilise comme 100-200KB pour moi, vous devrez peut-être le soustraire pour un montant plus précis.
Si vous souhaitez également ajouter une contrainte de temps, vous pouvez le faire assez facilement bash
(cela ne fonctionnera pas sh
):
cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n
La <(command)
chose semble être peu connue mais est souvent extrêmement utile, plus d'informations à ce sujet ici: http://tldp.org/LDP/abs/html/process-sub.html
Ensuite, pour l'utilisation de cat
: cat
attendra que les entrées soient complètes jusqu'à la sortie, et en maintenant l'un des tuyaux ouverts, grep restera actif.
Si vous avez pv
et souhaitez augmenter lentement l'utilisation de la RAM:
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
Le simple fait d'insérer la | pv |
pièce vous indiquera l'état actuel (débit et total, par défaut, je pense - sinon, voyez la page man (ual)).
Pourquoi une autre réponse? La réponse acceptée recommande d'installer un paquet (je parie qu'il y a une version pour chaque chipset sans avoir besoin d'un gestionnaire de paquet); la réponse la plus votée recommande de compiler un programme C (je n'avais pas de compilateur ni de chaîne d'outils à compiler pour votre plate-forme cible); la deuxième réponse la plus votée recommande d'exécuter l'application dans une VM (ouais, laissez-moi dd de la carte SD interne de ce téléphone via USB ou quelque chose du genre et créez une image de boîte virtuelle); la troisième suggère de modifier quelque chose dans la séquence d'amorçage qui ne remplit pas la RAM comme souhaité; le quatrième ne fonctionne que dans la mesure où le point de montage / dev / shm (1) existe et que (2) est grand (le remontage nécessite la racine); le cinquième combine plusieurs des éléments ci-dessus sans code exemple; la sixième est une excellente réponse mais je ne l’ai pas vue avant de proposer ma propre approche, alors j'ai pensé ajouter le mien, aussi parce que c'est plus court à retenir ou à taper si vous ne voyez pas que la ligne memblob est en réalité le noeud du problème; le septième encore 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 sommes tous très peu créatifs et finalement le dixième a écrit son propre programme C ++, ce qui pose le même problème que la réponse la plus votée.
set -e
, alors je viens d'apprendre quelque chose :)
time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n
(utiliser 10 Go de mémoire) prend 1 minute 46 secondes. L'exécution du programme eatmemory de julman99 à l' adresse github.com/julman99/eatmemory prend 6 secondes. ... Et bien, plus le temps de téléchargement et de compilation, mais compilé sans problème ... et très rapidement ... sur ma machine RHEL6.4. Pourtant, j'aime cette solution. Pourquoi réinventer la roue?
Je garde une fonction pour faire quelque chose de similaire dans mes fichiers de points. 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
}
Comment compter 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)
sysctl vm.swappiness=0
et définir de plus vm.min_free_kbytes sur un petit nombre, peut-être 1024. Je ne l'ai pas essayé, mais la documentation indique que c'est comme cela que vous contrôlez la rapidité de l'échange ... vous devriez le faire capable de le rendre assez lent, au point de provoquer une condition de MOO sur votre machine. Voir kernel.org/doc/Documentation/sysctl/vm.txt et kernel.org/doc/gorman/html/understand/understand005.html
Que diriez-vous de ramfs s'il existe? Montez-le et copiez-le sur un gros fichier? S'il n'y a ni /dev/shm
ramfs - je suppose un petit programme en C qui effectue un gros malloc en fonction d'une valeur d'entrée? Vous devrez peut-être 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 peut être préférable ulimit
de limiter la quantité de mémoire pouvant être allouée.
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.
Je pense que c’est le cas de poser la mauvaise question et de nuire à la santé mentale de personnes en compétition pour la réponse la plus créative. Si vous devez uniquement simuler les 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 doit libérer ou réallouer de la mémoire.