Astăzi dorim să vorbim despre câteva dintre cele mai recente actualizări ale sistemului Sherlock [un cluster de înaltă performanță al Universității Stanford - n. trad.], care accelerează semnificativ listarea fișierelor în directoare cu un număr mare de înregistrări.
Spre deosebire de articolele obișnuite, acesta este mai degrabă un raport intern despre cum se desfășoară munca constantă la Sherlock pentru a-l menține în cea mai bună formă pentru utilizatorii noștri. Sperăm să publicăm mai multe astfel de articole în viitor.
Listarea multor fișiere necesită timp
Totul a început cu o întrebare în suportul tehnic de la un utilizator. Acesta a raportat o problemă, că execuția ls dură câteva minute în directorul cu mai mult de 15.000 de înregistrări din $SCRATCH [director pentru fișiere temporare - n. trad.].
Mii de fișiere într-un singur director creează de obicei dificultăți pentru sistemul de fișiere și este cu siguranță nerecomandat. Utilizatorul știa acest lucru și a recunoscut că nu este bine, dar a menționat că pe laptopul său listarea se face de 1000 de ori mai repede decât în Sherlock. Desigur, asta ne-a deranjat. Așa că am săpat mai adânc.
Pentru că ls arată bine
Am analizat ce face de fapt ls când listează un director, și de ce procesul durează atât de mult. În majoritatea distribuțiilor moderne ls se execută implicit 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, permisiuni, mărci, atribute extinse și așa mai departe, pentru a alege culoarea corespunzătoare.
Una dintre soluțiile simple ale problemei este să dezactivăm complet culorile în ls, dar imaginați-vă indignarea utilizatorilor. Cu siguranță nu putem renunța la ieșirea colorată, nu suntem monștri.
Așa că am săpat mai adânc. ls înfățișează înregistrările prin variabila de mediu LS_COLORS, pe care o stabilește dircolors(1) pe baza fișierului de configurare dir_colors(5). Da, (și dacă nu știți despre fișierele (do), atunci dir_colors , indiferent de situație).
Hai să ne uităm mai în detaliu
Pentru a determina care dintre schemele de colorare cauzează încetinirea, am creat un mediu experimental:
$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # nu încercați asta acasă!
$ time ls --color=always $SCRATCH/dont | wc -l
10000
real 0m12.758s
user 0m0.104s
sys 0m0.699s12,7 secunde pentru 10 000 de fișiere, nu prea bine.
Apropo, ai nevoie de un flag
--color=always: deși acesta se referă lals --color=auto, darlsdetectează când nu este conectat la terminal (de exemplu, printr-un canal sau cu redirectarea ieșirii) și dezactivează colorarea, dacă este setatauto. Un tip deștept.
Deci ce durează atât de mult? Ne-am uitat cu ajutorul 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 000 apeluri lstat(), 10 000 apeluri getxattr() (care toate eșuează, pentru că în mediu nostru nu există atributele pe care le caută ls), 10 000 apeluri capget().
Cu siguranță asta poate fi optimizat.
Atributul capabilities? Nu.
Urmați sfaturile , am încercat să dezactivăm verificarea atributului :
$ 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, accelerare până la 8 secunde! Ne-am scăpat de toate aceste apeluri costisitoare getxattr(), iar apelurile capget() de asemenea, au dispărut, grozav.
Dar încă mai rămân aceste apeluri enervante lstat(), deși…
Câte culori sunt necesare?
Așa că am analizat mai în detaliu LS_COLORS.
La început, 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: $ unset LS_COLORS $ echo $LS_COLORS $ time ls --color=always $SCRATCH/dont | wc -l 10000 real 0m13.037s user 0m0.077s sys 0m1.092s
Ceva!?! Tot 13 secunde?
Se pare că atunci când variabila de mediu LS_COLORS nu este definită sau lipseste doar unul dintre elementele sale =color:, aceasta utilizează implicit baza de date încorporată și totuși folosește culori. Așadar, dacă vrei să dezactivezi colorarea pentru un anumit tip de fișier, trebuie să o suprascrii cu =: sau 00 în fișierul DIR_COLORS.
După multe încercări și greșeli, am restrâns căutarea la următoarele:
EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00ce se scrie ca
LS_COLORS='ex=00:su=00:sg=00:ca=00:' Aceasta înseamnă: nu colora fișierele după atribut , dar după biți , nici după .
Accelerăm ls
Și dacă nu facem niciuna din aceste verificări, apelurile lstat() dispar și acum este cu totul altceva:
$ 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.029s0,3 secunde pentru o listă de 10 000 de fișiere, un record.
Configurăm Sherlock
De la 13 secunde cu setările implicite la 0,3 secunde cu o mică configurare LS_COLORS înseamnă o accelerare de 40 de ori datorită absenței setuid / setgid și fișierelor executabile colorate. Nu este o pierdere atât de mare.
Desigur, acum este configurat în Sherlock pentru fiecare utilizator.
Dar dacă doriți să readuceți colorarea, puteți pur și simplu să reveniți la setările implicite:
$ unset LS_COLORS Dar atunci, la directoarele cu un număr mare de fișiere, asigurați-vă că pregătiți cafea, în timp ce funcționează. ls.
Sursa: habr.com
