Comment swapoff peut être si lent?

79

D'une manière ou d'une autre, j'ai échangé 14 Go de mémoire. Après avoir tué le coupable, j'ai à nouveau des tonnes de mémoire libre, alors j'ai pensé pouvoir à nouveau importer les données importantes . Donc, avec 5 Go sur 32 Go utilisés et 14 Go d'espace d'échange utilisés, j'ai couru swapoff -a... et 4 heures plus tard, environ la moitié du travail était terminée.

Cela signifie moins de 1 Mo / s, alors que je peux facilement copier 200 Mo / s. Mon swap est crypté, mais toutes les partitions normales le sont également. Avec aes-ni, cela ne génère aucune charge processeur sensible (et remplir l'espace de swap n'a pris que quelques minutes). Je vois qu'il n'y a pas de raison particulière d'optimiser swapoff, mais je me demande comment cela pourrait être aussi lent.


J'ajoute juste quelques données supplémentaires: Ma mémoire principale est de 32 Go et j’ai un espace d’échange de 32 Go sur chacun des 4 disques durs (sûrement trop, mais on s’en fiche de qui?). La totalité de l’espace de swap peut être (déchiffré et) lu en moins de 5 minutes:

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

Lire une partie d'une partition ne peut pas être plus lent que de tout lire. Pourtant, en lire environ un dixième prend environ 100 fois plus de temps.

J'ai observé que pendant les swapoffdeux processeurs, le processeur était principalement inactif (peut-être 10% d'un cœur), de même que les disques ("mesurés" par les voyants). J'ai aussi vu que les espaces de swap étaient éteints les uns après les autres.

maaartinus
la source
1
Je me demande si le même phénomène se produit lorsque le système charge par lui-même les pages permutées dans la RAM. Par exemple, si un système était suspendu sur le disque puis démarré, tout était basculé et il était chargé dans la RAM. Semble être très lent pour moi aussi.
Petr Pudlák
Tous les périphériques d'échange sont-ils activés avec la même priorité?
Nils
@Petr Pudlák: Suspendre sur disque est un peu différent, il écrit simplement le contenu de la RAM dans un espace libre dans la zone de swap, ce qui (et l'annulation de la suspension) est probablement beaucoup plus rapide. Je ne peux pas essayer car cela ne fonctionne pas avec le swap crypté.
Maaartinus
@Nils: Oui, la priorité est la même chose que le disque et son partitionnement.
Maaartinus
Cela le rend plus étrange. Dans ce cas, le swap est réparti sur tous les disques - cela devrait être très rapide. Est iostat -d 5- ce que vous avez également montré une faible IO sur les disques swapoff?
Nils

Réponses:

53

Tout d’abord, regardons ce que vous pouvez attendre de votre disque dur. Votre disque dur peut faire 200 Mo / s séquentiellement . Lorsque vous prenez en compte les temps de recherche, cela peut être beaucoup plus lent. Pour prendre un exemple arbitraire, consultez les spécifications de l'un des disques 3 To modernes de Seagate, le ST3000DM001 :

  • Débit de données soutenu maximum: 210 Mo / s

  • Recherche en lecture moyenne: <8,5 ms

  • Octets par secteur: 4 096

Si vous n'avez jamais besoin de chercher et si votre permutation est proche du bord du disque, vous pouvez vous attendre à atteindre le débit maximal = 210 Mo / s.

Mais si vos données de swap sont entièrement fragmentées, dans le pire des cas, vous devrez rechercher environ chaque secteur que vous lisez. Cela signifie que vous ne pouvez lire que 4 Ko toutes les 8,5 ms, ou 4 Ko / 0,0085 = 470 Ko / s

Donc, dès le départ, il n’est pas inconcevable que vous couriez à la vitesse supérieure.


Cela dit, il semble absurde de swapoffcourir si lentement et de devoir lire les pages dans le désordre, surtout si elles ont été écrites rapidement (ce qui implique dans l’ordre). Mais c’est peut-être ainsi que fonctionne le noyau. Le rapport de bogue Ubuntu n ° 486666 aborde le même problème:

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

L'une des réponses était:

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

Le rapport de bogue a été fermé non résolu.

Le livre de Mel Gorman " Comprendre le gestionnaire de mémoire virtuelle Linux " est un peu obsolète, mais convient qu'il s'agit d'une opération lente:

La fonction responsable de la désactivation d' une zone est assez prévisible, appelé sys_swapoff(). Cette fonction concerne principalement la mise à jour du fichier swap_info_struct. La tâche principale de la pagination dans chaque page paginée est la responsabilité try_to_unuse()qui coûte extrêmement cher.

Il y a eu un peu plus de discussions à partir de 2007 sur la liste de diffusion linux-kernel avec pour sujet " accélérer le swapoff " - bien que les vitesses qu'ils discutent y soient un peu plus élevées que ce que vous voyez.


C'est une question intéressante qui est probablement généralement ignorée car swapoffrarement utilisée. Je pense que si vous vouliez vraiment le localiser, la première étape consisterait à surveiller de plus près les habitudes d'utilisation de vos disques (avec atop, peut-être , iostatdes outils plus puissants, comme perfou systemtap). Les éléments à rechercher peuvent être une recherche excessive, de petites opérations d’E / S, une réécriture et un mouvement constants des données, etc.

Jim Paris
la source
5
Excellente explication. Il convient de noter qu'il est possible de contourner la majeure partie de la fragmentation et de libérer rapidement la majorité des échanges en effectuant un
Brandon DuPree
1
Ce n'est pas juste fragmentation / temps de recherche. Mon échange est sur SSD et les lectures aléatoires sont très rapides, mais la commande swapoff est beaucoup plus lente qu'elle ne le devrait et la charge de mon SSD est d'environ 1% util. Je soupçonne que la liste de lecture est impliquée quelque part dans le noyau ou dans swapoff (qui utilise environ 90 à 100% du processeur). Bien sûr, si tout le travail est effectué de manière séquentielle et que les recherches sur le disque sont lentes, elles peuvent s’ajouter considérablement.
Thomas Guyot-Sionnest le
34

J'ai eu le même problème avec mon ordinateur portable qui a un SSD, donc la recherche de temps ne devrait pas être un problème.

J'ai trouvé une explication alternative . Voici un extrait

Swapoff examine chaque page de mémoire remplacée dans la partition de swap et tente de trouver tous les programmes qui l'utilisent. S'il ne parvient pas à les trouver immédiatement, il examinera les tables de pages de chaque programme en cours d'exécution pour les trouver. Dans le pire des cas, il vérifiera toutes les tables de pages pour chaque page permutée de la partition. C'est vrai, les mêmes tables de pages sont vérifiées encore et encore.

C'est donc un problème de noyau plutôt que toute autre chose.

Nick Craig-Wood
la source
1
Non, ce n'est pas un problème de noyau IMHO. C'est comment swapoffest mis en œuvre. Lorsque le processus est remplacé, cela ne prend pas beaucoup de temps.
Marki555
15
C'est un problème avec l'implémentation de swapoff qui est dans le noyau - donc un problème de noyau! Vous pouvez voir si vous strace swapoffappelez l’ swapoffappel système.
Nick Craig-Wood
1
J'ai un serveur avec 48 Go de RAM (32cores), avait 6 Go d'échange de bogues gratuit était utilisé 0,7 Go. swappiness = 10, a essayé de le rendre 0 et a également essayé le swapoff afin de voir ce qui se passe. swapoff prend des âges, probablement 30 minutes, libérant le swap extrêmement lent. J'ai SSD sous presque aucune charge et le processeur est similaire, attendez-vous au processus de swapoff qui prend un processeur à 100%.
sorin
1
C'est le problème de la façon dont swapoff est implémenté (dans le noyau). Il y a eu des discussions sur une bien meilleure approche il y a quelques années dans kernel-dev, mais ils disent que c'est un cas en coin et ne veulent pas l'effort de le changer.
Marki555
7
Sur un serveur avec 1 To de RAM (oui, TB) et un swap de 2 Go (exigence SAP ridicule), le swapoff prenait 12 heures pour libérer 5% de ces 2 Go (avec 1 cpu à 100%).
Marki555
22

Eh oui, le swapoffmécanisme est horriblement inefficace. La solution de contournement est simple: parcourez les processus, mais plutôt les pages permutées. Utilisez ce script python (je ne suis pas affilié):

git clone https://github.com/wiedemannc/deswappify-auto

Notez que le mode de fonctionnement du démon concerne uniquement les ordinateurs de bureau / ordinateurs portables qui sont souvent en veille prolongée. Je ne l'exécuterais pas en tant que démon sur un système de serveur. Il suffit de l'exécuter au premier plan, d'attendre qu'il indique qu'il s'est occupé de certains processus, puis de l'arrêter et d'essayer:

swapoff /dev/x

Étant donné que la plupart des pages sont maintenant présentes à la fois dans les échanges et dans la mémoire, elles swapoffont très peu à faire et devraient être extrêmement rapides (j’ai vu des centaines de Mo / s).

Section d'histoire à venir

Le script python mentionné ci-dessus est basé sur le reste de cette réponse, ce qui a été mon amélioration par rapport à cette réponse plus ancienne écrite par jlong . Comme le script est beaucoup plus sûr, je recommande d' essayer le reste de ma réponse comme dernière ligne de défense :

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

Cela dure peut-être 2 secondes et ne fait vraiment rien, il vous suffit de lister les 10 premiers segments de mémoire (en fait, il imprime plus de one-liners; oui j'aime vraiment les one-liners; examinez simplement les commandes, acceptez le risque, copiez-collez-les dans votre shell, ceux-ci liront en fait de swap).

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

Le one-liner principal est sûr (pour moi), sauf qu'il lit beaucoup de / proc.

Les sous-commandes préparées pour votre examen manuel ne sont pas sécuritaires . Chaque commande suspendra un processus pendant la durée de lecture d'un segment de mémoire à partir de swap. C'est donc dangereux avec des processus qui ne tolèrent aucune pause. Les vitesses de transfert que j'ai vues étaient de l'ordre de 1 gigaoctet par minute. (Le script python susmentionné a supprimé cette lacune).

Un autre danger est d’exercer trop de pression sur la mémoire du système. Consultez donc la procédure habituelle. free -m

Qu'est ce que ça fait?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

La sortie de ce script Perl est une série de gdbcommandes dump memory (range)rappelant les pages échangées en mémoire.

La sortie commence par la taille, il est donc assez facile de la traverser | sort -Vr | headpour obtenir les 10 plus grands segments par taille (SSIZE). Le -Vsymbole correspond à un tri adapté au numéro de version, mais il fonctionne pour mon objectif. Je ne pouvais pas comprendre comment faire fonctionner le tri numérique.

Kubanczyk
la source
Vous voudriez utiliser le tri numérique ici avecsort -t = -k 2n
Stéphane Chazelas
9
Il ne semble pas nécessaire d’utiliser gdb pour jeter un coup d’œil sur la mémoire du processus (au moins sur les noyaux récents). On peut simplement ouvrir /proc/$pid/mem, chercher et lire directement. Voici PoC en grande partie en fonction de votre extrait: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae Ce processus de façon n'est pas arrêté, il ne devrait pas AFAIK être des dangers causés par cela.
WGH
10

Lors de la permutation, si un emplacement de swap en cours d'utilisation est détecté, le noyau commence par permuter dans la page. La fonction unuse_process () essaie ensuite de trouver toutes les entrées de table de page qui correspondent à la page qui vient d'être échangée et effectue la mise à jour nécessaire des tables de page. La recherche est exhaustive et prend beaucoup de temps: il visite tous les descripteurs de mémoire (du système entier) et examine ses entrées dans la table des pages une par une.

Veuillez vous référer à la page 724 de «Comprendre la 3ème version du noyau Linux».

Leslie
la source