Kada varijabla okruženja urbrzava proces 40 puta

Danas želite razgovarati o nekim najnovijim ažuriranjima sustava Sherlock [to je visoko performantni klaster Sveučilišta Stanford — napomena prevoditelja], koja značajno ubrzavaju nabrajanje datoteka u direktorijima s velikim brojem unosa.

Za razliku od običnih članaka, ovo je više insider izvještaj o tome kako se redovito radi na Sherlocku kako bismo ga održali u najboljem stanju za naše korisnike. Nadamo se da ćemo u budućnosti objaviti više takvih članaka.

Nabrajanje mnogih datoteka oduzima vrijeme

Sve je počelo s pitanjem u tehničkoj podršci od korisnika. Prijavio je problem da izvršenje ls traži nekoliko minuta u direktoriju s više od 15 000 unosa u $SCRATCH [direktorij za privremene datoteke — napomena prevoditelja].

Tisuće datoteka u jednom direktoriju obično stvaraju poteškoće za datotečni sustav i to se definitivno ne preporučuje. Korisnik je to znao i priznao da to nije dobro, ali je spomenuo da na svom laptopu nabrajanje traje 1000 puta brže nego u Sherlocku. Naravno, to nas je pogodilo. Stoga smo zavirili dublje.

Jer ls izgleda lijepo

Proučili smo što zapravo radi ls prilikom nabrajanja direktorija i zašto proces traje toliko vremena. U većini suvremenih distribucija ls podrazumijevano se izvršava kao ls --color=auto, jer svima se sviđa boja.

Ali lijepe boje imaju svoju cijenu: za svaku datoteku ls mora dobiti informacije o tipu datoteke, njenim dozvolama, zastavicama, proširenim atributima i slično, kako bi odabrao odgovarajuću boju.

Jedno od jednostavnih rješenja problema je potpuno isključiti boje u ls, ali zamislite ogorčenje korisnika. Ni u kojem slučaju ne možemo oduzeti kolorirane izlaze, nismo čudovišta.

Stoga smo zavirili dublje. ls boji unose putem varijable okruženja LS_COLORS, koju postavlja dircolors(1) na temelju konfiguracijske datoteke dir_colors(5).Da, izvršna datoteka čita konfiguracijsku datoteku kako bi stvorila varijablu okruženja koju onda koristi ls (a ako ne znate o datotekama door (do), onda dir_colors reagirati, bez obzira na sve).

Pogledajmo detaljnije

Kako bismo odredili koja shema bojenja uzrokuje usporavanje, stvorili smo eksperimentalno okruženje:

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # ne pokušavajte ovo kod kuće!
$ time ls --color=always $SCRATCH/dont | wc -l
10000

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

12,7 sekundi za 10 000 datoteka, nije baš dobro.

Usput, potrebna je zastavica --color=always: iako se obraća u ls --color=auto, ali ls otkriva kada nije povezan na terminal (na primjer, putem kanala ili s preusmjeravanjem izlaza) i isključuje bojanje ako je postavljena vrijednost auto. Pametan dečko.

Pa, što toliko traje? Pogledali smo uz pomoć strace:

$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% vrijeme     sekundi  mikroseundi/poziv     pozivi    greške 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
[...]

Lijepo: 10 000 poziva lstat(), 10 000 poziva getxattr() (svi su neuspješni jer u našem okruženju nema atributa koje traži ls), 10 000 poziva capget().

Svakako se ovo može optimizirati.

Atribut capabilities? Ne.

Prateći savjete greška od prije 10 godina, pokušali smo isključiti provjeru atributa capabilities:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% vrijeme     sekundi  mikroseundi/poziv     pozivi    greške 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 ukupno

stvarno    0m8.160s
korisnik    0m0.115s
sustav     0m0.961s

Wow, ubrzanje na 8 sekundi! Oslobodili smo se svih ovih skupih poziva getxattr(), a pozivi capget() su također nestali, super.

Ali još uvijek ostaju ti dosadni pozivi lstat(), iako…

Koliko je boja potrebno?

Zato smo se detaljnije pozabavili LS_COLORS.

Prvo smo samo isključili ovu varijablu:

$ 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

Što!?! I dalje 13 sekundi?

Čini se da kada je varijabla okruženja LS_COLORS nije definirana ili nedostaje samo jedan od njezinih elemenata =color:, prema zadanim postavkama koristi ugrađenu bazu podataka i još uvijek koristi boje. Stoga, ako želite onemogućiti bojanje za određenu vrstu datoteke, morate ju prepisati pomoću =: ili 00 u datoteci DIR_COLORS.

Nakon mnoštva pokušaja i pogrešaka suzili smo pretraživanje na ovo:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

što se zapisuje kao

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

To znači: ne boj datoteke prema atributu capabilities, nego prema bitovima setuid/setgid, niti po oznake izvršivosti.

Poboljšavamo ls

I ako ne napraviš nijednu od ovih provjera, tada se pozivi lstat() nestaju, i sada je to sasvim druga priča:

$ 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 ukupno

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

0,3 sekunde na popisu od 10 000 datoteka, rekord.

Postavljamo Sherlock

Od 13 sekundi s zadanim postavkama do 0,3 sekunde s malim podešavanjem LS_COLORS znači 40 puta brže zbog nedostatka setuid / setgid i obojenih izvršivih datoteka. Nije to velika žrtva.

Naravno, sada je to postavljeno u Sherlocku za svakog korisnika.

Ali ako želite vratiti boje, možete se jednostavno vratiti na postavke prema zadanim postavkama:

$ unset LS_COLORS

Ali tada, za direktorije s velikim brojem datoteka, obavezno skuhajte kavu dok traje ls.

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster