Wenn Umgebungsvariablen den Prozess um das 40-Fache beschleunigen

Heute möchten wir über einige aktuelle Updates des Sherlock-Systems [das ist ein Hochleistungs-Cluster der Stanford Universität – Anmerkung der Übersetzung] berichten, die das Auflisten von Dateien in Verzeichnissen mit vielen Einträgen erheblich beschleunigen.

Im Gegensatz zu herkömmlichen Artikeln handelt es sich hierbei eher um einen Insiderbericht darüber, wie die regelmäßige Pflege von Sherlock erfolgt, um es für unsere Nutzer optimal zu halten. Wir hoffen, in Zukunft mehr solcher Artikel zu veröffentlichen.

Das Auflisten vieler Dateien benötigt Zeit.

Alles begann mit einer Anfrage an den technischen Support von einem Nutzer. Er berichtete über ein Problem, dass die Ausführung ls in einem Verzeichnis mit mehr als 15.000 Einträgen mehrere Minuten in Anspruch nimmt für $SCRATCH [Verzeichnis für temporäre Dateien – Anmerkung der Übersetzung].

Tausende von Dateien in einem Verzeichnis schaffen normalerweise Schwierigkeiten für das Dateisystem und das wird definitiv nicht empfohlen. Der Nutzer war sich dessen bewusst und erkannte, dass es nicht ideal ist, erwähnte jedoch, dass das Auflisten auf seinem Laptop 1.000 Mal schneller erfolgt als in Sherlock. Das hat uns natürlich beschäftigt. Daher haben wir genauer hingeschaut.

Denn ls sieht gut aus.

Wir haben uns angesehen, was tatsächlich passiert. ls bei der Auflistung des Katalogs und warum dieser Prozess so viel Zeit in Anspruch nimmt. In den meisten modernen Distributionen ls wird standardmäßig ausgeführt als ls --color=auto, denn jeder mag Farben.

Aber schöne Farben haben ihren Preis: Für jede Datei ls muss die Information über den Dateityp, die Berechtigungen, Flags, erweiterte Attribute und Ähnliches erfasst werden, um die entsprechende Farbe auszuwählen.

Eine der einfachen Lösungen für das Problem besteht darin, die Farbe in ls ganz auszuschalten, aber stellen Sie sich das Entsetzen der Benutzer vor. Farbige Ausgaben dürfen auf keinen Fall entfernt werden, wir sind keine Ungeheuer.

Deshalb haben wir tiefer gegraben. ls färbt Einträge über die Umgebungsvariable LS_COLORS, die durch dircolors(1) basierend auf der Konfigurationsdatei dir_colors(5). Ja, die ausführbare Datei liest die Konfigurationsdatei, um die Umgebungsvariable zu erstellen, die dann von ls verwendet wird (und wenn Sie nicht über die Dateien door (do), dann dir_colors reagieren wird, trotzdem).

Lassen Sie uns genauer darauf eingehen.

Um herauszufinden, welches der Farbschemata die Verlangsamung verursacht, haben wir eine experimentelle Umgebung erstellt:

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # Versuch das nicht zu Hause!
$ time ls --color=always $SCRATCH/dont | wc -l
10000

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

12,7 Sekunden für 10.000 Dateien, nicht besonders gut.

Übrigens, das Flag ist erforderlich --color=always: obwohl es erkennt, ls --color=autoübertragen wird, jedoch ls wenn es nicht mit dem Terminal verbunden ist (zum Beispiel über eine Leitung oder mit Umleitung der Ausgabe) und die Farbgebung deaktiviert, wenn der Wert gesetzt ist auto. Cleverer Kerl.

Was dauert also so lange? Wir haben das mit angesehen strace:

$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% Zeit     Sekunden  usecs/Aufruf     Aufrufe    Fehler 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.000 Aufrufe lstat(), 10.000 Aufrufe getxattr() (die alle fehlschlagen, weil in unserer Umgebung keine Attribute vorhanden sind, die ls sucht), 10.000 Aufrufe capget().

Das lässt sich bestimmt optimieren.

Attribut capabilities? Nö

Basierend auf dem Rat eines 10 Jahre alten Bugs, wir haben versucht, die Attributprüfung zu deaktivieren Capabilities festzulegen.:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:/)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% Zeit     Sekunden  Mikrosekunden/Anruf     Anrufe    Fehler 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 insgesamt

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

Wow, Beschleunigung auf 8 Sekunden! Wir haben all diese teuren Aufrufe losgeworden getxattr(), und die Aufrufe capget() sind ebenfalls verschwunden, großartig.

Aber diese lästigen Aufrufe sind noch übrig lstat(), obwohl...

Wie viele Farben werden benötigt?

Deshalb haben wir uns das genauer angesehen LS_COLORS.

Zuerst haben wir einfach diese Variable 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, wenn die Umgebungsvariable LS_COLORS nicht definiert ist oder nur eines ihrer Elemente fehlt =color:, sie verwendet standardmäßig die integrierte Datenbank und nutzt dennoch Farben. Wenn Sie die Farbcodierung für einen bestimmten Dateityp deaktivieren möchten, müssen Sie sie mit =: oder 00 in der Datei DIR_COLORS.

Nach zahlreichen Versuchen und Fehlschlägen haben wir die Suche darauf eingegrenzt:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

was aufgezeichnet wird als

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

Das bedeutet: keine Dateien entsprechend den Attributen Capabilities festzulegen., sondern nach den Bits setuid/setgid, noch nach ausführbarkeitsflag.

Wir beschleunigen ls

Und wenn keine dieser Prüfungen durchgeführt wird, dann verschwinden die Aufrufe, und jetzt ist es ganz anders: lstat() $ 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 totalreal 0m0.337s user 0m0.032s sys 0m0.029s

$ export LS_COLORS='ex=00:su=00:sg=00:ca=00:'
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% Zeit     Sekunden  Mikrosekunden/Call     Aufrufe    Fehler 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 insgesamt

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

0,3 Sekunden für eine Liste von 10.000 Dateien, ein Rekord.

Wir konfigurieren Sherlock

Von 13 Sekunden mit den Standardeinstellungen auf 0,3 Sekunden mit einer kleinen Anpassung LS_COLORS bedeutet eine 40-fache Beschleunigung durch das Fehlen von setuid / setgid und farbigen ausführbaren Dateien. Kein großer Verlust.

Natürlich ist das jetzt in Sherlock für jeden Benutzer konfiguriert.

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

$ unset LS_COLORS

Aber dann sollten Sie sich einen Kaffee machen, während die Liste auf Katalogen mit vielen Dateien erstellt wird. ls.

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster