Lorsqu'une variable d'environnement accélère le processus de 40 fois

Aujourd'hui, nous voulons parler de certaines des dernières mises à jour du système Sherlock [il s'agit d'un cluster hautes performances de l'Université de Stanford - env. trans.], ce qui accélère considérablement le référencement des fichiers dans des répertoires comportant un grand nombre d'entrées.

Contrairement aux articles réguliers, il s'agit plutôt d'un rapport d'initié sur la façon dont nous travaillons régulièrement sur Sherlock pour qu'il fonctionne au mieux pour nos utilisateurs. Nous espérons publier davantage d’articles comme celui-ci à l’avenir.

Lister de nombreux fichiers prend du temps

Tout a commencé avec une question d'assistance technique d'un utilisateur. Il a signalé le problème que l'exécution ls prend quelques minutes dans un répertoire contenant plus de 15 000 entrées $SCRATCH [répertoire pour les fichiers temporaires - env. voie].

Des milliers de fichiers dans un répertoire représentent généralement une charge pour le système de fichiers et ne sont absolument pas recommandés. L'utilisateur le savait et a admis que ce n'était pas bon, mais a mentionné que le listing était 1000 fois plus rapide sur son ordinateur portable que sur Sherlock. Bien sûr, cela nous a blessé. Nous avons donc cherché plus profondément.

Parce que ça a l'air sympa

Nous avons regardé ce que ça fait réellement ls lors de l'inscription d'un répertoire et pourquoi le processus prend si longtemps. Sur la plupart des distributions modernes ls par défaut, il fonctionne comme ls --color=auto, parce que tout le monde aime les couleurs.

Mais les belles couleurs ont un prix : pour chaque fichier ls doit obtenir des informations sur le type de fichier, ses autorisations, ses indicateurs, ses attributs étendus, etc. afin de sélectionner la couleur appropriée.

Une solution simple au problème consiste à désactiver complètement la couleur dans ls, mais imaginez l'indignation des utilisateurs. Vous ne devez en aucun cas supprimer la sortie couleur, nous ne sommes pas des monstres.

Nous avons donc cherché plus profondément. ls entrées de couleurs via une variable d'environnement LS_COLORS, qui est fixé dircolors(1) basé sur le fichier de configuration dir_colors(5)... Oui, l'exécutable lit le fichier de configuration pour créer une variable d'environnement, qui ls utilise ensuite (et si vous ne connaissez pas les fichiers porte (faire), puis dir_colors fonctionnera, Malgré tout).

Regardons de plus près

Pour déterminer quelle palette de couleurs provoque le ralentissement, nous avons créé un environnement expérimental :

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # don't try this at home!
$ time ls --color=always $SCRATCH/dont | wc -l
10000

real    0m12.758s
user    0m0.104s
sys     0m0.699s

12,7 secondes pour 10 000 fichiers, ce qui n'est pas très bon.

Au fait, nous avons besoin d'un drapeau --color=always: bien qu'il se tourne vers ls --color=automais ls détecte quand il n'est pas connecté à un terminal (par exemple par tuyau ou avec redirection de sortie) et désactive la coloration s'il est défini sur auto. Gars intelligent.

Alors, qu'est-ce qui prend autant de temps ? Nous avons regardé avec strace:

$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 44.21    0.186617          19     10000           lstat
 42.60    0.179807          18     10000     10000 getxattr
 12.19    0.051438           5     10000           capget
  0.71    0.003002          38        80           getdents
  0.07    0.000305          10        30           mmap
  0.05    0.000217          12        18           mprotect
  0.03    0.000135          14        10           read
  0.03    0.000123          11        11           open
  0.02    0.000082           6        14           close
[...]

Waouh : 10 000 appels lstat(), 10 000 appels getxattr() (qui échouent tous parce que notre environnement n'a pas les attributs recherchés par ls), 10 000 appels capget().

Cela peut sûrement être optimisé.

Attribut de capacités ? Non

Suite des conseils bug d'il y a 10 ans, nous avons essayé de désactiver la vérification des attributs capacités:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:/)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 98.95    0.423443          42     10000           lstat
  0.78    0.003353          42        80           getdents
  0.04    0.000188          10        18           mprotect
  0.04    0.000181           6        30           mmap
  0.02    0.000085           9        10           read
  0.02    0.000084          28         3           mremap
  0.02    0.000077           7        11           open
  0.02    0.000066           5        14           close
[...]
------ ----------- ----------- --------- --------- ----------------
100.00    0.427920                 10221         6 total

real    0m8.160s
user    0m0.115s
sys     0m0.961s

Wow, jusqu'à 8 secondes d'accélération ! Nous nous sommes débarrassés de tous ces appels coûteux getxattr(), et les défis capget() disparu aussi, super.

Mais il y a toujours ces appels ennuyeux lstat(), Bien que…

De combien de fleurs avez-vous besoin ?

Nous avons donc regardé de plus près LS_COLORS.

Nous avons d’abord simplement désactivé cette variable :

$ echo $LS_COLORS
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
$ unset LS_COLORS
$ echo $LS_COLORS

$  time ls --color=always $SCRATCH/dont | wc -l
10000

real    0m13.037s
user    0m0.077s
sys     0m1.092s

Quoi!?! Encore 13 secondes ?

Il s'avère que lorsque la variable d'environnement LS_COLORS un seul de ses éléments n'est pas défini ou est manquant <type>=color:, il utilise la base de données intégrée par défaut et utilise toujours les couleurs. Donc, si vous souhaitez désactiver la colorisation pour un certain type de fichier, vous devez la remplacer par <type>=: ou <type> 00 dans le fichier DIR_COLORS.

Après de nombreux essais et erreurs, nous avons limité notre recherche à ceci :

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

qui s'écrit comme

LS_COLORS='ex=00:su=00:sg=00:ca=00:'

Cela signifie : ne coloriez pas les fichiers par attribut. capacités, mais petit à petit setuid/setgid, ni par indicateur d'exécutabilité.

Nous accélérons ls

Et si vous ne faites aucune de ces vérifications, alors appelez lstat() disparaître, et maintenant c'est une tout autre affaire :

$ export LS_COLORS='ex=00:su=00:sg=00:ca=00:'
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 63.02    0.002865          36        80           getdents
  8.10    0.000368          12        30           mmap
  5.72    0.000260          14        18           mprotect
  3.72    0.000169          15        11           open
  2.79    0.000127          13        10           read
[...]
------ ----------- ----------- --------- --------- ----------------
100.00    0.004546                   221         6 total

real    0m0.337s
user    0m0.032s
sys     0m0.029s

0,3 seconde sur une liste de 10 000 fichiers, un record.

Configurer Sherlock

De 13 secondes avec les paramètres par défaut à 0,3 seconde avec des ajustements mineurs LS_COLORS signifie une accélération de 40 fois en raison de l'absence setuid / setgid et des fichiers exécutables colorés. Ce n’est pas une si grosse perte.

Bien entendu, cela est désormais configuré dans Sherlock pour chaque utilisateur.

Mais si vous souhaitez restituer la coloration, vous pouvez simplement revenir aux paramètres par défaut :

$ unset LS_COLORS

Mais dans les répertoires contenant beaucoup de fichiers, assurez-vous de préparer du café pendant son exécution. ls.

Source: habr.com

Ajouter un commentaire