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,
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 sprels --color=auto
Darls
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ă laauto
. 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
$ 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.
, nici de
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