Swap, RAM swapiness etc

Bonjour à tous,

Après des mois à arpenter le web, je me résous à poser la question dans un forum:
Comment indiquer à mon noyau de NE RIEN entreposer dans ma partition swap?

J’ai une Debian récente avec noyau 4.14, mais le problème persiste depuis mes débuts sur Linux il y a plus d’un an, qu’importe la version du noyau.

Ma partition swap est de 4 Go tandis que ma RAM est de 8 Go, ce qui fonctionne parfaitement en compressant l’image de la RAM lors de l’hibernation (uswsusp fait très bien cela avec s2disk). Sauf quand plein de processus se mettent à placer des données sur la partition swap. Or cela arrive tout le temps, alors que ça ne devrait jamais arriver puisqu’à ce jour, la RAM utilisée sur ma machine n’a jamais dépassé les 5 Go (en comptant les caches).

De plus ma mémoire de masse est un SSD, donc j’aimerais autant éviter les écritures inutiles pour favoriser sa longévité.

J’ai trouvé un petit script qui permet de voir les processus qui mettent leurs données sur le swap, et c’est principalement WebContent/Firefox (les onglets ouverts mais non consultés depuis un moment), divers services de Gnome (evolution, calendriers, navigateur Nautilus…) et LibreOffice qui placent des choses sur la partition swap.

J’ai bien sûr essayé de jouer avec vm.swappiness (à 10, puis 1, puis 0) et avec vm.vfs_cache_pressure (à 400 ou à 1000). Ça n’a jamais changé plus de 10 ou 20 % de l’occupation de ma partition swap. Il est possible qu’il faille paramétrer les seuils du démon swapd mais je ne trouve pas de documentation là-dessus. Peut-être devrai-je remplacer le swapd d’origine par un autre daemon…

Du coup, mes mises en hibernation échouent régulièrement à cause du manque d’espace sur le swap (alors que j’ai 4 Go de libre en RAM). Je me retrouve donc souvent à faire des swapoff / swapon pour nettoyer mon swap ou à fermer des applications/onglets que j’aurais préféré garder pour diminuer son occupation et permettre à l’image d’hibernation d’y tenir.

Quelqu’un connaît ce problème ou a une solution?

As-tu essayé d’activer zswap pour compresser les données écrites dans le swap ?

Son s2disk fait déjà la compression.

@bigderf Pas d’idée de comment traiter le problème, mais au lieu de s2disk seul, tu n’as qu’à faire un swapoff -a && swapon -a && s2disk non ?

Sinon, j’ai des vieux HD ide de quelques dizaines de Go qui doivent trainer si besoin: je te donne ça si tu habites pas loin (14). :smiley:

A moins que quelque chose m’échappe, s2disk ne compresse que les données présentes en mémoire, pas les données déjà écrites dans le swap. Sinon cela ne devrait faire aucune différence que des données soient déjà dans le swap ou pas, l’espace nécessaire à l’hibernation serait le même.

Salut
bien curieux cette utilisation du swap

Même avec les réglages suivant dans /etc/sysctl.conf mon swap n’est pratiquement jamais utilisé

vm.swappiness=75
vm.vfs_cache_pressure=50
vm.overcommit_memory=2
vm.overcommit_ratio=10

cf https://www.kernel.org/doc/Documentation/sysctl/vm.txt

 free
              total        used        free      shared  buff/cache   available
Mem:        3788272     1724620      936040       49220     1127612     1762652
Swap:       7852028           0     7852028

Et avec 8 onglets dans firefox , ça va pas pisser loin

root@debian:/# free
              total        used        free      shared  buff/cache   available
Mem:        3788272     2211920      181364       54444     1394988     1250544
Swap:       7852028        2480     7849548

Avec libreoffice en plus

# free
              total        used        free      shared  buff/cache   available
Mem:        3788272     2350440      245816       74504     1192016     1094660
Swap:       7852028       12740     7839288

En plus lisisble

 free -h
              total        used        free      shared  buff/cache   available
Mem:           3,6G        2,3G        186M         71M        1,1G        1,0G
Swap:          7,5G         12M        7,5G

Tu arrives vraiment a consommer tant de swap?? alors que tu as 8 Go de RAM?
Vérifies avec

free -h

Dans mes souvenirs il me revient une règle qui disait que pour éviter tout problème:
swap=2*RAM

D’autres part si tu as peur d’écrire sur ton ssd, tu n’es pas obligé de mettre le swap sur ton ssd , tu peux utiliser une partition d’un autre disque
https://wiki.debian.org/fr/Swap

Cette “règle” est obsolète, et aberrante avec les quantités de RAM actuelles.
Par contre à la lumière de cette discussion il semble que la recommandation d’avoir au moins autant de swap que de RAM pour l’hibernation reste d’actualité.

Et bonjour l’augmentation du temps d’entrée et de sortie de l’hibernation. Le swap est un des meilleurs candidats à mettre sur SSD.

Oui, par contre l’installateur de Debian, si on choisit un partitionnement automatique, continue à appliquer cette règle (en tout cas la dernière fois que j’ai essayé, sur l’installateur de Jessie).

Le choix des tailles des partitions par l’installateur Debian en mode assisté est discutable, et pas que pour le swap.

En tout cas la doc officielle dit ça

En ce qui concerne la taille de la partition d’échange (swap), les avis sont partagés. Une règle traditionnelle, qui fonctionne bien, est d’utiliser autant d’espace d’échange que de RAM. Dans la plupart des cas, cette taille ne devrait pas être inférieure à 16 Mo. Bien sûr, il y a des exceptions à cette règle. Si vous essayez de résoudre simultanément 10 000 équations sur une machine avec 256 Mo de RAM, vous pourriez avoir besoin d’un gigaoctet (ou plus) d’échange.

_Sur certaines architectures 32 bits (m68k et PowerPC), la taille maximale d’une partition d’échange est de 2 Go. Cela devrait suffire pour presque tous les systèmes.

De toute façon, si vos besoins en espace d’échange sont aussi importants, vous devriez probablement essayer de disperser les partitions d’échange sur des disques différents (appelés aussi « spindles ») et, si possible, sur des canaux IDE ou SCSI différents. Le noyau équilibrera l’utilisation de l’espace d’échange entre les différentes partitions, afin d’obtenir de meilleures performances.

Avec une machine possédant 32 Mo de RAM et un disque IDE de 1,7 Go sur /dev/sda, on pourrait créer une partition de 500 Mo pour un système sur /dev/sda1, une partition d’échange de 32 Mo sur /dev/sda3 et une partition Linux d’environ 1,2 Go sur /dev/sda2.

https://www.debian.org/releases/stable/amd64/apcs03.html.fr

:open_mouth: ce serait sans doute pas inutile que cette doc soit mise à jour avec des valeurs un peu plus contemporaines. On peut raisonnablement douter de la pertinence de recommandations aussi datées (ça existait même pas le canal SATA ?!?). Enfin, si les mainteneurs de la doc ont laissé ça tel quel, les principes n’ont pas dû tellement changer, mais vu de l’extérieur ça fait bizarre.

Je me suis fait la même réflexion en lisant ce passage.

Que ça existe ou pas, c’est peu pertinent ici car le bus SATA est de type point à point et ne permet de connecter qu’un seul disque qui bénéficie donc de toute la bande passante du bus (exception faite des multiplicateurs de ports SATA qui semblent rares), alors que les bus SCSI et IDE permettent de connecter plusieurs disques (2 pour l’IDE, jusqu’à 15 pour le SCSI) qui doivent se partager la bande passante du bus.

swapoff est très long. Je n’ai pas envie d’attendre 15-30 minutes chaque fois que je veux arrêter de travailler…

Quant aux vieux HD, je doute qu’ils puissent faire l’affaire, et je suis en plus très loin ! :wink:

J’obtiens de beaux chiffres comme les tiens quand je viens de démarrer (après un arrêt système). Mais au fur et à mesure des jours qui passent, ce qui est peu ou pas utilisé est mis en swap. Il suffit par exemple que je re-visite des onglets laissés à l’abandon depuis des jours pour voir l’occupation de mon swap diminuer aussitôt (enfin… aussi vite que possible, c’est-à-dire au rythme de quelques dizaines de Mo par seconde).

J’ai vu récemment une page qui détaille le calcul que fait le noyau pour mettre des pages en swap, et cela implique effectivement la notion de “old page” et “new page”. Mais je ne sais pas comment influer dessus.

Concernant ta dernière remarque, je n’ai qu’un SSD (c’est un ordinateur portable).

Pour quelle occupation du swap ?
Cela me semble totalement anormal. Il ne faut pas 15 minutes pour lire moins de 4 Gio, surtout depuis un SSD. Cela équivaut à un débit de moins de 5 Mo/s, n’importe quel disque dur asthmatique fait mieux.

Tu n’aurais pas des tmpfs anormalement remplis ? A vérifier avec

df -hT

Note : le pseudo-fichier /proc/meminfo contient des informations plus détaillées que free sur l’utilisation de la mémoire.

Je m’étais mis en tête que la longueur du swapoff était due au fait que ça passait par un mécanisme compliqué de “reclaim” des pages et de calcul de ré-allocation de mémoire vive. Je n’y connais pas grand chose. Mais si effectivement il ne s’agit que de lire le swap et de l’écrire en RAM, alors c’est anormalement long. Dans mon cas, j’ai peut-être un peu exagéré (je suis originaire de Marseille). Disons que pour 2 Go de swap occupé, il faut 5 bonnes minutes. Si les données à récupérer sont des tout petits morceaux de moins de 4 ko répartis aléatoirement, ça peut expliquer la lenteur. Les SSD ne font guère mieux que les disques pour ce genre de données.

Là je viens de redémarrer mon système, j’ai 30 onglets ouverts dans Firefox et il n’y a rien sur le swap. Normal puisque rien n’a été laissé à l’abandon depuis un certain temps.

Je n’ai aucune idée de ce qu’est un tmpfs, encore moins de quand on peut les considérer comme trop remplis. mais la commande que tu me donnes affiche ceci (sur une session toute fraîche, donc):

tmpfs              778M     12M  767M   2% /run
tmpfs              3,8G     27M  3,8G   1% /dev/shm
tmpfs              5,0M       0  5,0M   0% /run/lock
tmpfs              3,8G       0  3,8G   0% /sys/fs/cgroup
tmpfs              778M     12K  778M   1% /run/user/132
tmpfs              778M     68K  778M   1% /run/user/1000

S’il y a suffisamment de mémoire libre, il n’y a pas de raison de réclamer de la mémoire allouée aux caches de page ou VFS. Dans le cas contraire, il faudra vider du cache, et dans le cas où une page du cache est “dirty” (modifiée en cache), il faudra l’écrire sur disque avant.

Au contraire, la réduction du temps d’accès est un des atouts majeurs des SSD par rapport aux disques durs. Les premiers SSD n’allaient pas beaucoup plus vite que les disques durs contemporains en débit séquentiel (et parfois moins vite en écriture), mais étaient imbattables en temps d’accès : ça passe de 10 ms à moins de 1 ms.

2 Go en 5 minutes, ça fait un débit moyen de moins de 7 Mo/s.

Un tmpfs est un système de fichiers temporaire en mémoire virtuelle (RAM et swap si nécessaire). C’est utilisé pour stocker des fichiers temporaires (/run) ou comme mécanisme de mémoire partagée (/dev/shm). /tmp lui-même peut être en tmpfs. Ici il n’y a que des tmpfs à usage système, et ils sont très peu remplis, comme il se doit. Mais il faudrait regarder lorsque le système a commencé à swapper.
Attention aussi à /dev qui utilise une variante de tmpfs, devtmpfs. Normalement son occupation est quasi-nulle car il ne contient que des pseudo-fichiers de périphériques, mais j’ai vu un cas où l’utilisateur avait créé par erreur un fichier /dev/sdX occupant tout l’espace en croyant écrire dans un périphérique /dev/sdX inexistant.

Mon /dev est indiqué à 0% d’occupation.

J’ai continué mes tests et investigations.

https://linux-mm.org/PageReplacementDesign

Dans le noyau, la gestion de mémoire est faite par un mécanisme dit “S-LRU” qui tient compte des coûts d’allocation de RAM cache ou de place dans le swap en fonction de leurs structures. Je n’ai pas vraiment compris grand chose, mais en tout cas certains types de données n’étant pas liées à un système de fichier “normal”, il n’existe pas de table de contenu et toute la zone de mémoire doit donc être parcourue depuis son commencement jusqu’à ce qu’on tombe sur le segment voulu. Apparemment, cela occasionne de sérieuses problématiques pour les machines qui ont plusieurs dizaines de Go de mémoire vive (dont une bonne partie de mémoire cache/partagée), sur les serveurs ou les calculateurs. Dans ces textes techniques, il est donc stipulé que lire/écrire dans le swap est quatre fois plus lent que de le faire dans un système de fichier “normal”. (Mais il est possible que j’aie mal compris).

J’ai refait mon test en évitant les tâches de fond, et vider 2,6 Go de swap m’a pris 3 minutes, ce qui fait 12 Go/s, ce qui voudrait dire que mon SSD fait du 48 Go/s sur des systèmes de fichiers normaux. C’est conforme aux performances attendues pour des fichiers de 4 ko. Pour mémoire, quand le site “lesnumeriques.com” avait testé ce SSD, ils écrivaient :
“Avec 64 Mo/s en écriture de petits fichiers (4 Ko) et 33 Mo/s en lecture, il se classe dans la moyenne [des SSD]. Des résulats qui demeurent toutefois bien au-delà de ce que peuvent offrir les disques durs classiques.”

En fait, ce qui se passe, c’est que les données mises en swap lors d’une hibernation ne sont que très peu récupérées en mémoire vive lors du réveil de ma machine (à moins d’aller solliciter ces données en sélectionnant à nouveau les onglets ou fichiers ouverts un à un). Hibernation après hibernation, j’ai donc un swap qui enfle et n’est jamais nettoyé spontanément. Je crains donc qu’il n’y ait aucune solution à mon problème, autre que passer quelques minutes à faire un swapoff régulièrement.

En tout cas, merci à tous de vous être penchés sur la question ! Bonne journée et au plaisir…

Où as-tu lu cela exactement ? La seule mention d’un facteur 4 que je vois dans le document pointé par l’URL ci-dessus est la suivante, presque à la fin :

(assume swap IO is 4x as expensive as file IO?)

Il s’agit seulement d’une hypothèse de travail, et cela concerne le coût total de la mise en swap (entrée et sortie), pas seulement la sortie.

Tu veux dire Mo/s ?

Pourquoi ne pas essayer d’activer zswap pour compresser les données mises en swap comme je l’ai suggéré ?
Ou augmenter la taille du swap, tout simplement ?

En tout cas, cela n’explique pas pourquoi avec swappiness=0 et de la mémoire libre, une telle quantité de swap est utilisée. Il pourrait être intéressant de lancer vmstat avec une période de ton choix et d’enregistrer sa sortie dans un fichier pour pouvoir retrouver les instants et les conditions d’occupation de la mémoire où des mises en swap se sont produites.

je crains donc qu’il n’y ait aucune solution à mon problème, autre que passer quelques minutes à faire un swapoff régulièrement.

Pourquoi pas utiliser anacron et mettre un script qui fait swapoff dans /etc/cron.weekly ?

Effectivement je me suis référé à l’hypothèse de la fin, n’y comprenant pas grand chose et trouvant que ça concordait avec le fait qu’il faille parcourir tout le swap car c’est de la mémoire “anonyme”. Mais à vrai dire je n’en sais rien.

Oui, je voulais dire Mo/s, désolé…

Je ne connais pas zswap. J’hiberne en utilisant uswsusp avec s2disk et la compression maximale, et en théorie il ne devait y avoir que ça dans le swap. Peut-être devrais-je essayer zswap en effet, en espérant que ça n’impactera pas les performances… Quant à augmenter le swap, je l’ai déjà fait en passant de 3 à 4 Go, sachant que l’image de ma RAM pour l’hibernation fait typiquement entre 1 et 2 Go.

Mais bon, j’ai 8 Go de RAM et 256 Go de SSD, sur un ordinateur qui me sert à énormément de choses, de l’édition vidéo au traitement statistique d’ensembles de données en passant par du Microsoft Office / PowerShell (avec une -forcément- lourde partition Windows 10 pour être 100% compatible avec mes clients), un peu de développement avec Eclipse, virtual box et des vdi pour simuler des réseaux, plus toute ma musique (64 Go) sans laquelle je ne pourrais pas vivre :wink:

Donc chaque Go est précieux, chaque partition n’a que 10 ou 20% de libre, et j’aimerais éviter d’augmenter le swap.

Quant à savoir pourquoi le swap est utilisé, les explications que j’ai trouvées m’ont convaincu. Contrairement à ce qu’on peut lire dans beaucoup de fora, swappiness=0 n’a jamais voulu dire que la mise en swap est désactivée. La formule de décision pour mettre des données en swap, qui se trouve dans le fichier vmscan.c, est de la forme:
swap_tendency = mapped_ratio / 2 + distress + swappiness

Où distress est un nombre de 0 à 100 qui augmente au fur et à mesure des échecs d’allocation de mémoire vive (qui eux-mêmes dépendent de la pression de cache réglée par d’autres paramètres et de la gourmandise des processus en train de tourner). Bref, même avec un swappiness négatif (ce que j’aurais volontiers essayé si j’étais certain de ne pas tout faire planter), le noyau mettrait des choses en swap. De plus, j’ai lu dans d’autres docs que le noyau n’est jamais très désireux de récupérer les données du swap car c’est également coûteux et -en général- inutile sauf si ces données sont explicitement demandées par un processus. Donc les données mises en swap pour l’hibernation ont toutes les chances d’y rester pour l’encombrer tant qu’elles ne sont pas à nouveau sollicitées. Cela semble être confirmé par ce que j’observe au gré des hibernations successives.