Comment utiliser l'espace de swap uniquement en cas d'urgence?

41

J'ai un ordinateur portable Debian (Buster) avec 8 Go de RAM et 16 Go d'échange. Je lance une très longue tâche en cours d'exécution. Cela signifie que mon ordinateur portable est resté allumé pendant les six derniers jours pendant qu'il passe à travers.

Ce faisant, je dois régulièrement utiliser mon ordinateur portable comme ordinateur portable. Cela ne devrait pas être un problème. la tâche longue est liée aux E / S, passe par des tâches sur un disque dur USB et ne nécessite pas beaucoup de RAM (<200 Mo) ou de CPU (<4%).

Le problème est que lorsque je reviendrai à mon ordinateur portable au bout de quelques heures, ce sera très lent et 30 minutes peuvent être nécessaires pour revenir à la normale. Cela est si grave que les contrôleurs d'incident signalent que leurs applications respectives sont gelées (en particulier les fenêtres du navigateur) et que les incidents qui se produisent entraînent une défaillance incorrecte.

En regardant sur le moniteur système, des 2,5 Go utilisés, environ la moitié est basculée en swap. J'ai confirmé le problème en supprimant l'espace de permutation ( swapoff /dev/sda8). Si je le laisse sans espace d'échange, il revient à la vie presque instantanément, même après 24 heures. Avec swap, c'est pratiquement une brique pour les cinq premières minutes, n'ayant été laissée que six heures. J'ai confirmé que l'utilisation de la mémoire ne dépasse jamais 3 Go, même en mon absence.

J'ai essayé de réduire le swappiness ( voir aussi: Wikipedia ) aux valeurs de 10et 0, mais le problème persiste. Il semble qu'après un jour d'inactivité, le noyau estime que la totalité de l'interface graphique n'est plus nécessaire et l'efface de la mémoire vive (la permute sur le disque). La longue tâche consiste à lire une vaste arborescence de fichiers et à lire chaque fichier. Il se peut donc que le noyau ait du mal à croire que la mise en cache aiderait. Toutefois, sur un seul disque dur USB HD de 2 To avec environ 1 milliard de noms de fichiers, une Go de RAM supplémentaire n’aidera pas beaucoup les performances. Ceci est un ordinateur portable pas cher avec un disque dur lent. Il ne peut tout simplement pas charger les données dans la RAM assez rapidement.

Comment puis-je dire à Linux d'utiliser uniquement l'espace de swap en cas d'urgence? Je ne veux pas courir sans échange. Si quelque chose d'inattendu se produit et que le système d'exploitation a soudainement besoin de quelques Go supplémentaires, je ne veux pas que les tâches soient détruites et je préférerais commencer à utiliser le swap. Mais pour le moment, si je laisse la permutation d'échange activée, mon ordinateur portable ne peut tout simplement pas être utilisé quand j'en ai besoin.

La définition précise du terme "urgence" pourrait faire l’objet d’un débat. Mais pour clarifier ce que je veux dire: une urgence serait où le système est laissé sans autre option que d’échanger ou de tuer des processus.


Qu'est-ce qu'une urgence? - As-tu vraiment besoin de demander? ... J'espère que tu ne te retrouveras jamais dans un immeuble en feu!

Il m'est impossible de définir tout ce qui pourrait constituer une urgence dans cette question. Mais par exemple, une urgence peut survenir lorsque le noyau est tellement sollicité pour la mémoire qu'il a commencé à tuer des processus avec le KOM Killer . Une urgence n'est PAS lorsque le noyau pense qu'il peut améliorer les performances en utilisant swap.


Final Edit: j'ai accepté une réponse qui répond exactement à ce que j'ai demandé au niveau du système d'exploitation. Les futurs lecteurs devraient également prendre note des réponses proposant des solutions au niveau de l'application.

Philip Couling
la source
11
Définissez le terme "urgence" et indiquez en quoi cela diffère de toute situation ordinaire dans laquelle un échange serait utilisé.
Kusalananda
4
Je voulais savoir si vous vouliez définir d'une manière ou d'une autre un type spécial "d'événement d'urgence" en dehors des limites qui permettrait au noyau d'utiliser l'échange, mais cet échange ne serait autrement pas utilisé. De toute façon, la pagination AFAIK sur la mémoire est lente et ne se fait que de manière «en cas d’urgence», et le mot «swappiness» est la seule chose que vous pouvez utiliser pour ajuster ce comportement (mais je ne suis pas un utilisateur Linux).
Kusalananda
2
Non ce n'est pas correct. Ce n'est pas seulement fait en cas d'urgence. À tout le moins, je pensais que ma question indiquait clairement que je n'utilisais que 3 Go sur 8 Go ... Ce n'est pas une urgence, mais le noyau est en train de permuter de toute façon. Je suggère que vous lisiez sur swappiness et les sujets environnants. Il y a beaucoup de discussions sur les différentes raisons de l'échange. Il est plausible que je demande un concept qui n'existe pas dans le noyau, mais les raisons pour lesquelles je le demande sont raisonnablement bien justifiées.
Philip Couling Le
4
Je reconnais que le conseil a toujours été "ne jamais courir sans échange". Mais la taille de la mémoire a réduit les vitesses de lecture / écriture de disque dur (disque dur non SSD), ce qui signifie que l’échange est de plus en plus une mauvaise idée. On a l'impression que certains croient que 8 Go de RAM + 8 Go d'échange permettront d'effectuer 16 Go de RAM + 0 échange. Si c'est vraiment le cas, il y a quelque chose qui ne va pas avec le noyau Linux.
Philip Couling le
7
@Philip Couling: Non, le fait est que 16 Go de RAM + 16 Go d’échange seront supérieurs aux échanges de 16 Go à 0 échange - en particulier lorsque votre code nécessite 17 Go de mémoire :-)
jamesqf

Réponses:

11

Avoir un échange aussi important de nos jours est souvent une mauvaise idée. Au moment où le système d'exploitation n'a échangé que quelques Go de mémoire, votre système avait déjà explosé (comme ce que vous avez vu).

Il est préférable d' utiliser zramavec une petite partition d'échange de sauvegarde . De nombreux systèmes d'exploitation tels que ChromeOS, Android et diverses distributions Linux activent zram par défaut depuis des années, en particulier pour les systèmes dotés de moins de RAM. C'est beaucoup plus rapide que le swap sur disque dur et vous pouvez clairement sentir la réactivité du système dans ce cas. Moins sur un SSD, mais selon les résultats du test de performance, cela semble toujours plus rapide, même avec l'algorithme lzo par défaut. Vous pouvez passer à lz4 pour des performances encore meilleures avec un taux de compression légèrement inférieur. Sa vitesse de décodage est presque 5 fois plus rapide que celle de LZO, selon les critères officiels.

Il y a aussi zswapbien que je ne l'ai jamais utilisé. Probablement la peine d'essayer et comparer lequel est le mieux pour vos cas d'utilisation

Après cela, une autre suggestion consiste à réduire la priorité de ces processus liés aux entrées-sorties et à laisser éventuellement un terminal s'exécutant sur une priorité plus élevée afin que vous puissiez exécuter des commandes sur celui-ci immédiatement même lorsque le système est chargé.

Lectures complémentaires

phuclv
la source
Juste pour que je comprenne, vous dites que je peux créer un zrampériphérique en mode bloc, l’utiliser comme swap, avec un swap de priorité inférieure comme partition de disque dur?
Philip Couling
@ PhilipCouling si vous utilisez un disque dur, alors oui, vous devez absolument utiliser un zram ou des solutions similaires. La priorité du swap doit être inférieure à celle de zram, afin que Linux tente d’utiliser d’abord le zram, puis prend en compte le swap. Si vous utilisez Ubuntu, le paquet zram-config gère déjà les paramètres de priorité pour vous
phuclv
3
J'accepte cette réponse car elle semble faire exactement ce que j'ai demandé. Si mon swap de 16 Go est toujours activé avec une priorité réduite, le noyau ne l'utilisera que lorsque zswap sera épuisé. IE: "en cas d'urgence". Remarque sur debian-buster, il est très facile à configurer, simplement en installant zram-tools.
Philip Couling
25

Un correctif consiste à vérifier que le contrôleur cgroup de mémoire est activé (je pense que c'est par défaut dans les noyaux même semi-récents, sinon vous devrez ajouter des éléments cgroup_enable=memoryà la ligne de commande du noyau). Vous pouvez ensuite exécuter votre tâche intensive d'E / S dans un groupe de contrôle avec une limite de mémoire, ce qui limite également la quantité de mémoire cache qu'il peut consommer.

Si vous utilisez systemd, vous pouvez définir +MemoryAccounting=yeset MemoryHigh/ MemoryMaxou MemoryLimit(dépend de si vous utilisez cgroup v1 ou v2) dans l’unité ou une tranche le contenant. Si c'est une tranche, vous pouvez utiliser systemd-runpour exécuter le programme dans la tranche.

Exemple complet d’un de mes systèmes pour l’exécution de Firefox avec une limite de mémoire. Notez que ceci utilise cgroups v2 et qu'il est configuré en tant qu'utilisateur, pas en tant qu'utilisateur root (l'un des avantages de v2 par rapport à v1 est que la délégation de cette opération à non-root est sûre, donc c'est ce que systemd fait).

$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &

J'ai trouvé que pour que l'utilisateur travaille, je devais utiliser une tranche. Le premier système fonctionne simplement en mettant les options dans le fichier de service (ou en utilisant systemctl set-propertyle service).

Voici un exemple de service (utilisant cgroup v1), notez les deux dernières lignes. Cela fait partie de l'instance système (pid = 1).

[Unit]
Description=mount S3QL filesystem
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
User=s3ql-user
Group=s3ql-user
LimitNOFILE=20000
ExecStartPre=+/bin/sh -c 'printf "S3QL_CACHE_SIZE=%%i\n" $(stat -c "%%a*%%S*.90/1024" -f /srv/s3ql-cache/ | bc) > /run/local-s3ql-env'
ExecStartPre=/usr/bin/fsck.s3ql  --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo  --log none «REDACTED»
EnvironmentFile=-/run/local-s3ql-env
ExecStart=/usr/bin/mount.s3ql --keep-cache --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo --cachesize ${S3QL_CACHE_SIZE} --threads 4
ExecStop=/usr/bin/umount.s3ql /mnt/S3QL/
TimeoutStopSec=2m
MemoryAccounting=yes
MemoryLimit=1G

La documentation est en systemd.resource-control(5).

derobert
la source
1
Ne pouvez-vous pas faire quelque chose de comparable et de portable en utilisant simplement ulimit?
Old Pro
1
@ OldPro pas vraiment. Tout d’abord, AFAIK n’a aucune idée de l’utilisation totale de la mémoire, y compris du cache de page (c’est l’utilisation qui devient excessive ici). Deuxièmement, ulimit pour la mémoire est per-process, les groupes de contrôle fonctionnent même si la tâche de longue durée se divise.
derobert
Je pensais que la raison pour laquelle la comptabilisation de la mémoire est activée par défaut sur les systèmes plus récents est due à une modification de la systemdversion 238 .
sourcejedi le
1
@sourcejedi c'est relativement récent. Lorsque le contrôleur de mémoire a été introduit pour la première fois, sa disponibilité (même non utilisée) entraînait un coût de performances suffisamment important pour que certaines distributions le désactivent au moins par défaut et vous deviez passer cet argument de ligne de commande du noyau pour l'activer. Les problèmes de performance ont été corrigés, donc cela a changé, et plus récemment, systemd l’active également par défaut.
derobert
14

Il semble qu'après un jour d'inactivité, le noyau estime que la totalité de l'interface graphique n'est plus nécessaire et l'efface de la mémoire vive (la permute sur le disque).

Le noyau fait The Right Thing ™ en le croyant. Pourquoi garderait-il 1 mémoire inutilisée dans la RAM et la gaspillerait donc au lieu de l’utiliser comme cache ou quelque chose de ce genre?

Je ne pense pas que le noyau Linux permute les pages de manière gratuite ou anticipée. Par conséquent, si cela se produit, vous devez stocker autre chose sur de la RAM, ce qui améliore les performances de votre tâche de longue durée, ou du moins avec cet objectif.

Si vous savez à quel moment vous devez réutiliser votre ordinateur portable à l’avance, vous pouvez utiliser la atcommande (ou crontab) pour planifier un nettoyage de swap ( swapoff -a;swapon -a).

Comme le nettoyage de l’échange risque d’être excessif et même de déclencher le tueur de MOO si, pour une raison quelconque, tout ne tient pas dans la RAM, vous pouvez simplement "annuler l’échange" 2 de tout ce qui concerne les applications en cours que vous souhaitez réactiver.

Une façon de le faire consiste à attacher un débogueur similaire gdbà chacun des processus affectés et à déclencher une génération de vidages mémoire:

# gdb -p <pid>
...
generate-core-dump /dev/null
...
quit

Comme vous l'avez écrit, votre longue application ne réutilise pas les données lues après le premier passage. Vous êtes donc dans un cas spécifique où la mise en cache à long terme n'est pas utile. Ensuite, contourner le cache en utilisant une E / S directe comme suggéré par Will Crawford devrait être une bonne solution de contournement.

Sinon, vous pourriez régulièrement vider le cache de fichiers en écho 1ou 3le /proc/sys/vm/drop_cachespseudo-fichier avant le système d' exploitation pense qu'il est une bonne idée d'échanger vos applications graphiques et de l' environnement.

Voir Comment vider les mémoires tampons et le cache sur un système Linux? pour plus de détails.

1 Inutilisé en ce sens: plus utilisé activement depuis une période de temps significative, la mémoire étant toujours pertinente pour ses propriétaires.
2 Remettez dans la RAM les pages stockées dans la zone de swap.

jlliagre
la source
2
Merci pour la pensée sur les causes possibles. J'ai ajouté un peu à la question car cela pourrait être pertinent. Je me demande s'il existe un moyen de réduire la priorité de la mise en cache par rapport à la mémoire de l'application.
Philip Couling
5
"Je ne pense pas que le noyau Linux permute les pages de manière gratuite ou anticipée, donc s'il le fait, il doit consister à stocker autre chose sur la RAM, améliorant ainsi les performances." - Je pense que cette formulation est un peu ambiguë. Le noyau écrira définitivement les pages à permuter, chaque fois qu'il en aura l'occasion (par exemple, il y a peu d'E / S de disque). Cela ne les supprimera toutefois pas de la RAM. De cette façon, vous avez le meilleur des deux mondes: si vous avez rapidement besoin de ces pages, elles sont déjà dans la RAM et il n’ya rien à faire. Si une urgence (comme le dit le PO) se produit, vous devez simplement libérer ces pages en RAM, car
Jörg W Mittag
3
… Ils sont déjà en échange. Et c'est précisément la raison pour laquelle vous ne pas à utiliser swap « uniquement en cas d' urgence », car en cas d'urgence, le système est déjà en situation de stress et la dernière chose que vous voulez est d' ajouter de grandes quantités de disque E / S à cela.
Jörg W Mittag Le
2
Ce qui l’échange est probablement le long processus: c’est l’accès aux fichiers sur le disque. Ces fichiers en mémoire auront été utilisés plus récemment que la mémoire de l'interface graphique.
jpmc26 le
3
@ JörgWMittag Avez-vous la preuve que le noyau Linux, lorsque l'utilisation des E / S est faible, écrit préemptivement des pages sur la zone d'échange "au cas où", c'est-à-dire sans les libérer de la RAM?
Jlliagre le
10

Le processus que vous exécutez est-il quelque chose que vous avez créé vous-même?

Si tel est le cas, il pourrait être intéressant d’ajuster votre code pour ouvrir les fichiers à l’aide du O_DIRECTdrapeau, qui cite la page de manuel -

Essayez de minimiser les effets de cache des E / S vers et depuis ce fichier. En général, cela dégrade les performances, mais cela s'avère utile dans des situations spéciales, par exemple lorsque les applications font leur propre mise en cache. Les entrées / sorties de fichiers sont effectuées directement vers / depuis les tampons d'espace utilisateur. L'indicateur O_DIRECT s'efforce à lui seul de transférer des données de manière synchrone, mais ne donne pas les garanties de l'indicateur O_SYNC que les données et les métadonnées nécessaires sont transférées. Pour garantir des E / S synchrones, O_SYNC doit être utilisé en plus de O_DIRECT. Voir NOTES ci-dessous pour une discussion plus approfondie.

Will Crawford
la source
1
Une autre solution similaire (mais sans doute plus facile, car je suis à peu près sûr que O_DIRECT impose des restrictions d’alignement et que vous réduirez les performances si vos lectures ne sont pas volumineuses) consiste à dire au noyau que vous n’aurez plus besoin de ces données, en les effaçant de la liste. cache de page. (par téléphone ou fournir des liens, désolé)
derobert
1
@derobert D'une part, la nocachecommande est un hack pratique pour le faire. (LD_PRELOAD est utilisé pour détourner certains appels de la libc).
sourcejedi le
6

Voici une idée que je n'ai pas essayée moi-même (et je suis désolée de ne pas avoir le temps de faire des expériences avec cela).

Supposons que vous créiez une petite machine virtuelle avec seulement 512 Mo de mémoire pour votre traitement en arrière-plan. Je ne suis pas sûr que vous souhaitiez un échange, votre appel, et le désactiver sur votre système hôte.

X Tian
la source
3

Supprimez le swap ou diminuez-le d’environ 20% (cela peut varier selon les systèmes ), car récemment, les systèmes d’exploitation n’utilisent plus le swap de la même manière qu’il ya quelques années. Cela répond probablement à certaines de vos questions:

-> redhat.com officiel

certaines des infos Red Hat ci-dessous,

Dans le passé, certains éditeurs d’applications recommandaient d’échanger une taille égale à la RAM, voire deux fois plus. Imaginons maintenant le système susmentionné avec 2 Go de RAM et 2 Go d’échange. Une base de données sur le système a été configurée par erreur pour un système doté de 5 Go de RAM. Une fois la mémoire physique épuisée, l'échange est utilisé. Comme le disque d'échange est beaucoup plus lent que la RAM, les performances diminuent et des ralentissements se produisent. À ce stade, même les connexions au système peuvent devenir impossibles. Au fur et à mesure que de plus en plus de mémoire est écrite, les mémoires physique et d'échange sont complètement épuisées et le tueur OOM entre en action, tuant un ou plusieurs processus. Dans notre cas, il y a beaucoup de swaps disponibles, le temps de mauvaise performance est donc long.

et

https://wiki.debian.org/Swap

portion du lien Debian ci-dessus,

Informations et considérations relatives à la quantité de swap à utiliser:

"La quantité recommandée d'espace de permutation correspond généralement au double de la quantité de mémoire système. Au fil du temps, elle est passée à une fois et demie la mémoire système. Il existe de nombreuses variables concernant votre système et l'utilisation prévue qui détermineront l'échange système que vous souhaitez effectuer. "

Vous pouvez essayer:

"Le meilleur moyen de désactiver swap sous Linux"


Note personnelle:


Depuis que j'ai 6 Go de RAM et dans tous mes OS récemment sous Linux. Je n'ai jamais vu aucune indication d'utilisation de Swap. J'ai déterminé que je devais l' éteindre soit pour l'espace (quelques giga-octets de plus), soit parce que cela ralentissait parfois mon système.

Tyþë-Ø
la source
1
Dans le passé, certains éditeurs d’applications recommandaient d’échanger une taille égale à la RAM, voire deux fois plus. Je me sens beaucoup plus âgé en voyant cela, d'une façon ou d'une autre ... Même si j'ai encore l'un des disques durs à la barrière de ~ 528 Mo et aussi une mémoire de 2,5 Go, cette citation - en fait, c'est quelque chose d'il y a si longtemps ... Citation intéressante et cela pourrait expliquer pourquoi j'ai vu des problèmes similaires il y a quelques années. Je crois que j’ai utilisé sysctl pour résoudre ce problème, mais je ne me souviens pas exactement du réglage si c’était la veille.
Pryftan