Când o variabilă de mediu accelerează procesul de 40 de ori

Astăzi vrem să vorbim despre unele dintre cele mai recente actualizări ale sistemului Sherlock [acesta este un cluster de înaltă performanță la Universitatea Stanford - aprox. trans.], care accelerează semnificativ listarea fișierelor în directoare cu un număr mare de intrări.

Spre deosebire de articolele obișnuite, acesta este mai degrabă un raport din interior despre modul în care lucrăm în mod regulat la Sherlock pentru a menține funcționarea optimă pentru utilizatorii noștri. Sperăm să publicăm mai multe articole ca acesta în viitor.

Listarea multor fișiere necesită timp

Totul a început cu o întrebare de asistență tehnică din partea unui utilizator. El a raportat problema pe care execuția ls durează câteva minute într-un director cu peste 15 de intrări $SCRATCH [director pentru fișiere temporare - aprox. BANDĂ].

Mii de fișiere dintr-un singur director reprezintă de obicei o povară pentru sistemul de fișiere și cu siguranță nu sunt recomandate. Utilizatorul știa acest lucru și a recunoscut că nu a fost bine, dar a menționat că listarea a fost de 1000 de ori mai rapidă pe laptopul său decât Sherlock. Desigur, asta ne-a rănit. Așa că ne-am uitat mai adânc.

Pentru că arată bine

Ne-am uitat la ce face de fapt ls când listați un director și de ce procesul durează atât de mult. Pe majoritatea distribuțiilor moderne ls implicit rulează ca ls --color=auto, pentru că tuturor le plac culorile.

Dar culorile frumoase au un preț: pentru fiecare fișier ls trebuie să obțină informații despre tipul fișierului, permisiunile acestuia, steagurile, atributele extinse și altele asemenea pentru a selecta culoarea corespunzătoare.

O soluție simplă la problemă este dezactivarea completă a culorii în ls, dar imaginați-vă indignarea utilizatorilor. În niciun caz nu trebuie să eliminați rezultatul de culoare, nu suntem monștri.

Așa că ne-am uitat mai adânc. ls intrări de culori prin variabila de mediu LS_COLORS, care este setat dircolors(1) bazat pe fișierul de configurare dir_colors(5)... Da, executabilul citește fișierul de configurare pentru a crea o variabilă de mediu, pe care apoi o folosește (și dacă nu știți despre fișiere uşă (do), apoi dir_colors va functiona, In ciuda a tot).

Să aruncăm o privire mai atentă

Pentru a determina ce schemă de culori cauzează încetinirea, am creat un mediu experimental:

$ 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 secunde pentru 10 de fișiere, nu foarte bine.

Apropo, avem nevoie de un steag --color=always: deşi se întoarce spre ls --color=autoDar ls detectează când nu este conectat la un terminal (de exemplu, prin conductă sau cu redirecționare la ieșire) și dezactivează colorarea dacă este setată la auto. Tip inteligent.

Deci ce durează atât de mult? Ne-am uitat cu 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 de apeluri lstat(), 10 de apeluri getxattr() (care toate eșuează pentru că mediul nostru nu are atributele pe care ls le caută), 10 de apeluri capget().

Cu siguranță acest lucru poate fi optimizat.

Atributul capacităților? nu

Urmând sfatul bug de acum 10 ani, am încercat să dezactivăm verificarea atributelor capacități:

$ 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

Uau, până la 8 secunde de accelerație! Am scăpat de toate apelurile astea scumpe getxattr(), și provocări capget() a dispărut și el, grozav.

Dar mai există aceste apeluri enervante lstat(), Cu toate că…

De câte flori ai nevoie?

Prin urmare, ne-am uitat mai atent LS_COLORS.

Mai întâi am dezactivat pur și simplu această variabilă:

$ 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

Ce!?! Mai sunt 13 secunde?

Se pare că atunci când variabila de mediu LS_COLORS doar unul dintre elementele sale nu este definit sau lipsește <type>=color:, folosește baza de date încorporată în mod implicit și folosește în continuare culori. Deci, dacă doriți să dezactivați colorarea pentru un anumit tip de fișier, trebuie să o înlocuiți cu <type>=: sau <type> 00 în dosar DIR_COLORS.

După multe încercări și erori, ne-am restrâns căutarea la aceasta:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

care este scris ca

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

Aceasta înseamnă: nu colorați fișierele după atribut. capacități, dar puțin câte puțin setuid/setgid, nici de steag de executabilitate.

Accelerăm ls

Și dacă nu faci niciuna dintre aceste verificări, atunci apelează lstat() dispar, iar acum este o cu totul alta chestiune:

$ 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 secunde pe o listă de 10 de fișiere, un record.

Stabilirea lui Sherlock

De la 13 secunde cu setările implicite la 0,3 secunde cu ajustări minore LS_COLORS înseamnă o accelerație de 40 de ori din cauza absenței setuid / setgid și fișiere executabile colorate. Nu este o pierdere atât de mare.

Desigur, acest lucru este acum configurat în Sherlock pentru fiecare utilizator.

Dar dacă doriți să returnați colorarea, puteți pur și simplu să reveniți la setările implicite:

$ unset LS_COLORS

Dar apoi, în directoarele cu o mulțime de fișiere, asigurați-vă că preparați cafea în timp ce rulează ls.

Sursa: www.habr.com

Adauga un comentariu