Quand une variable d'environnement accélère le processus par 40 fois

Aujourd'hui, nous souhaitons parler de certaines des dernières mises à jour du système Sherlock [c'est un cluster haute performance de l'Université de Stanford — note du traducteur], qui accélèrent considérablement le listing des fichiers dans des répertoires avec un grand nombre d'entrées.

Contrairement aux articles habituels, il s'agit plutôt d'un rapport d'insider sur le travail régulier réalisé sur Sherlock pour le maintenir en excellente condition pour nos utilisateurs. Nous espérons publier davantage de tels articles à l'avenir.

Lister de nombreux fichiers prend du temps.

Tout a commencé par une demande au support technique de la part d'un utilisateur. Il a signalé un problème, précisant que l'exécution ls prenait plusieurs minutes dans un répertoire contenant plus de 15 000 entrées dans $SCRATCH [répertoire pour fichiers temporaires — note du traducteur].

Des milliers de fichiers dans un même répertoire créent généralement des difficultés pour le système de fichiers et cela n'est absolument pas recommandé. L'utilisateur le savait et a reconnu que c'était problématique, mais il a mentionné que sur son ordinateur portable, le listing s'effectuait 1000 fois plus vite qu'avec Sherlock. Bien sûr, cela nous a interpellés. Nous avons donc enquêté plus profondément.

Parce que ls a l'air bien.

Nous avons examiné ce que fait réellement ls lors du listing d'un répertoire, et pourquoi le processus prend autant de temps. Dans la plupart des distributions modernes, ls ls est exécuté par défaut comme ls --color=auto, car tout le monde aime la couleur.

Mais ces belles couleurs ont un prix : pour chaque fichier, ls il doit obtenir des informations sur le type de fichier, ses permissions, ses drapeaux, ses attributs étendus, etc., afin de choisir la couleur appropriée.

Une des solutions simples au problème est de désactiver entièrement la couleur dans ls, mais imaginez l'indignation des utilisateurs. Il est hors de question de retirer la sortie colorée, nous ne sommes pas des monstres.

C'est pourquoi nous avons investigué plus en profondeur. ls ls colorie les entrées via la variable d'environnement LS_COLORS, qui est définie par dircolors(1) sur la base du fichier de configuration dir_colors(5). Oui,l'exécutable lit le fichier de configuration pour créer la variable d'environnement, qui est ensuite utilisée par ls (et si vous ne connaissez pas les fichiers door (do), dir_colors fonctionnera , quoi qu'il arrive).Examinons cela de plus près.

Pour déterminer laquelle des schémas de coloration cause le ralentissement, nous avons créé un environnement expérimental :

Pour déterminer laquelle des configurations de coloration cause des ralentissements, nous avons créé un environnement expérimental :

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # ne le faites pas chez vous !
$ time ls --color=always $SCRATCH/dont | wc -l
10000

réel    0m12.758s
utilisateur    0m0.104s
système     0m0.699s

12,7 secondes pour 10 000 fichiers, ce n'est pas incroyable.

Au fait, il faut un drapeau --color=always: même s'il se transforme en ls --color=auto, mais ls il détecte quand il n'est pas connecté au terminal (par exemple, par un pipeline ou avec une redirection de sortie) et désactive la coloration si la valeur est réglée sur auto. 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
% temps     secondes  microsecondes/appel     appels    erreurs appel système
------ ----------- ----------- --------- --------- ----------------
 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
[...]

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

Cela peut probablement être optimisé.

Attributs de capacités ? Non.

En suivant les conseils de un bug vieux de 10 ans, nous avons essayé de désactiver la vérification des attributs des capacités:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% temps     secondes  microsecondes/appel     appels    erreurs appel système
------ ----------- ----------- --------- --------- ----------------
 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

réel    0m8.160s
utilisateur    0m0.115s
système     0m0.961s

Wow, réduisant à 8 secondes ! Nous nous sommes débarrassés de tous ces appels coûteux getxattr(), et les appels capget() ont également disparu, super.

Mais il reste encore ces appels ennuyeux lstat(), bien que…

Combien de couleurs faut-il ?

Nous avons donc examiné cela 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:
$ 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!?! Toujours 13 secondes?

Apparemment, lorsque la variable d'environnement LS_COLORS n'est pas définie ou qu'il manque un de ses éléments =color:, elle utilise par défaut une base de données intégrée et utilise tout de même des couleurs. Par conséquent, si vous souhaitez désactiver la coloration pour un type de fichier spécifique, vous devez la redéfinir avec :=: ou 00 dans le fichier DIR_COLORS.

Après de nombreuses essais et erreurs, nous avons réduit la recherche à ceci :

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

qui est enregistré comme

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

Cela signifie : ne pas colorer les fichiers selon les attributs des capacités, ni par les bits setuid/setgid, ni par le drapeau d'exécution.

Accélérer ls

Et si aucune de ces vérifications n'est effectuée, alors les appels lstat() disparaissent, et maintenant c'est tout autre chose :

$ 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 secondes pour une liste de 10 000 fichiers, un record.

Configuration de Sherlock

De 13 secondes avec les paramètres par défaut à 0,3 seconde avec un léger ajustement LS_COLORS cela signifie un accélération de 40 fois grâce à l'absence setuid / setgid et les fichiers exécutables coloriés. Pas une si grande perte.

Bien sûr, c'est maintenant configuré dans Sherlock pour chaque utilisateur.

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

$ unset LS_COLORS

Mais alors, pour les répertoires avec un grand nombre de fichiers, il est indispensable de préparer un café pendant que cela fonctionne. ls.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster