Wenn eine Umgebungsvariable den Prozess um das 40-fache beschleunigt

Heute möchten wir über einige der neuesten Updates des Sherlock-Systems sprechen [dies ist ein Hochleistungscluster an der Stanford University – ca. trans.], was das Auflisten von Dateien in Verzeichnissen mit vielen Einträgen erheblich beschleunigt.

Im Gegensatz zu normalen Artikeln ist dies eher ein Insiderbericht darüber, wie wir regelmäßig an Sherlock arbeiten, damit es für unsere Benutzer optimal läuft. Wir hoffen, in Zukunft weitere Artikel dieser Art veröffentlichen zu können.

Das Auflisten vieler Dateien nimmt Zeit in Anspruch

Alles begann mit einer technischen Supportfrage eines Benutzers. Er meldete das Problem, dass die Hinrichtung ls dauert in einem Verzeichnis mit über 15 Einträgen ein paar Minuten $SCRATCH [Verzeichnis für temporäre Dateien – ca. Fahrbahn].

Tausende Dateien in einem Verzeichnis stellen meist eine Belastung für das Dateisystem dar und sind definitiv nicht zu empfehlen. Der Benutzer wusste das und gab zu, dass es nicht gut war, erwähnte jedoch, dass die Auflistung auf seinem Laptop 1000-mal schneller war als bei Sherlock. Das hat uns natürlich wehgetan. Also schauten wir tiefer.

Weil ls gut aussieht

Wir haben uns angeschaut, was es tatsächlich leistet ls beim Auflisten eines Verzeichnisses und warum der Vorgang so lange dauert. Auf den meisten modernen Distributionen ls Standardmäßig läuft es als ls --color=auto, weil die Farben jedem gefallen.

Aber schöne Farben haben ihren Preis: für jede Datei ls muss Informationen über den Dateityp, seine Berechtigungen, Flags, erweiterten Attribute und dergleichen einholen, um die entsprechende Farbe auszuwählen.

Eine einfache Lösung für das Problem besteht darin, die Farbe in ls ganz zu deaktivieren, aber stellen Sie sich die Empörung der Benutzer vor. Auf keinen Fall sollte man die Farbausgabe wegnehmen, wir sind keine Monster.

Also schauten wir tiefer. ls Farbeinträge über Umgebungsvariable LS_COLORS, die eingestellt ist dircolors(1) basierend auf der Konfigurationsdatei dir_colors(5). Ja, Die ausführbare Datei liest die Konfigurationsdatei, um eine Umgebungsvariable zu erstellen, die ls dann verwendet (Und wenn Sie sich mit Dateien nicht auskennen mit (tun), dann dir_colors wird funktionieren, Trotzdem).

Lass uns genauer hinschauen

Um festzustellen, welches Farbschema die Verlangsamung verursacht, haben wir eine experimentelle Umgebung erstellt:

$ 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 Sekunden für 10 Dateien, nicht sehr gut.

Übrigens brauchen wir eine Flagge --color=always: obwohl er sich umdreht ls --color=autoAber ls erkennt, wenn es nicht mit einem Terminal verbunden ist (z. B. per Pipe oder mit Ausgabeumleitung) und deaktiviert die Farbgebung, wenn es auf eingestellt ist auto. Schlauer Typ.

Warum dauert es so lange? Wir schauten mit 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
[...]

Wow: 10 Anrufe lstat(), 10 Anrufe getxattr() (die alle fehlschlagen, weil unsere Umgebung nicht über die Attribute verfügt, nach denen ls sucht), 10 Aufrufe capget().

Sicherlich lässt sich das optimieren.

Attribut „Fähigkeiten“? Nein

Befolgen Sie den Rat Fehler von vor 10 Jahrenhaben wir versucht, die Attributprüfung zu deaktivieren Fähigkeiten:

$ 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, bis zu 8 Sekunden Beschleunigung! Wir haben all diese teuren Anrufe abgeschafft getxattr()und Herausforderungen capget() ist auch verschwunden, super.

Aber es gibt immer noch diese nervigen Anrufe lstat(), Obwohl…

Wie viele Blumen brauchen Sie?

Deshalb haben wir genauer hingeschaut LS_COLORS.

Zuerst haben wir diese Variable einfach deaktiviert:

$ 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

Was!?! Immer noch 13 Sekunden?

Es stellt sich heraus, dass die Umgebungsvariable LS_COLORS nur eines seiner Elemente ist nicht definiert oder fehlt <type>=color:, verwendet es standardmäßig die integrierte Datenbank und verwendet weiterhin Farben. Wenn Sie also die Einfärbung für einen bestimmten Dateityp deaktivieren möchten, müssen Sie sie mit überschreiben <type>=: oder <type> 00 im Ordner DIR_COLORS.

Nach vielen Versuchen und Irrtümern haben wir unsere Suche auf Folgendes eingegrenzt:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

was geschrieben wird als

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

Das bedeutet: Dateien nicht nach Attributen einfärben. Fähigkeiten, aber Stück für Stück setuid/setgid, weder von Ausführbarkeitsflag.

Wir beschleunigen ls

Und wenn Sie keine dieser Prüfungen durchführen, dann rufen Sie an lstat() verschwinden, und jetzt ist es eine ganz andere Sache:

$ 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 Sekunden auf einer Liste von 10 Dateien, ein Rekord.

Sherlock einrichten

Von 13 Sekunden mit Standardeinstellungen auf 0,3 Sekunden mit geringfügigen Anpassungen LS_COLORS bedeutet eine 40-fache Beschleunigung aufgrund der Abwesenheit setuid / setgid und farbige ausführbare Dateien. Kein so großer Verlust.

Natürlich wird dies jetzt in Sherlock für jeden Benutzer konfiguriert.

Wenn Sie die Farbgebung jedoch wiederherstellen möchten, können Sie einfach zu den Standardeinstellungen zurückkehren:

$ unset LS_COLORS

Stellen Sie jedoch sicher, dass bei Verzeichnissen mit vielen Dateien der Kaffee während des Betriebs zubereitet wird ls.

Source: habr.com

Kommentar hinzufügen