Ko spremenljivka okolja pospeši proces za 40-krat

Danes želimo govoriti o nekaterih najnovejših posodobitvah sistema Sherlock [to je visoko zmogljiva gruča na Univerzi Stanford - pribl. prev.], ki bistveno pohitri izpisovanje datotek v imenike z velikim številom vnosov.

V nasprotju z običajnimi članki je to bolj kot notranje poročilo o tem, kako redno delamo na Sherlocku, da bi zagotovil najboljše delovanje za naše uporabnike. Upamo, da bomo v prihodnosti objavili več takšnih člankov.

Seznam številnih datotek zahteva čas

Vse se je začelo z vprašanjem tehnične podpore uporabnika. Je poročal o težavi, ki jo je izvedba ls traja nekaj minut v imeniku z več kot 15 vnosi $SCRATCH [imenik za začasne datoteke - pribl. vozni pas].

Na tisoče datotek v enem imeniku običajno predstavlja breme za datotečni sistem in vsekakor ni priporočljivo. Uporabnik je to vedel in priznal, da ni dobro, vendar je omenil, da je bil seznam na njegovem prenosniku 1000-krat hitrejši kot Sherlock. Seveda nas je to prizadelo. Zato smo pogledali globlje.

Ker izgleda lepo

Pogledali smo, kaj dejansko počne ls pri navajanju imenika in zakaj postopek traja tako dolgo. Na večini sodobnih distribucij ls privzeto teče kot ls --color=auto, saj so barve všeč vsem.

Toda lepe barve imajo svojo ceno: za vsako datoteko ls mora pridobiti podatke o vrsti datoteke, njenih dovoljenjih, zastavicah, razširjenih atributih in podobno, da izbere ustrezno barvo.

Ena preprosta rešitev problema je, da v celoti onemogočite barvo v ls, a predstavljajte si ogorčenje uporabnikov. V nobenem primeru ne smete odvzeti barvnega izpisa, nismo pošasti.

Zato smo pogledali globlje. ls barvne vnose prek spremenljivke okolja LS_COLORS, ki je nastavljen dircolors(1) na podlagi konfiguracijske datoteke dir_colors(5). da izvršljiva datoteka prebere konfiguracijsko datoteko, da ustvari spremenljivko okolja, ki jo nato uporabi (in če se ne spoznate na datoteke vrata (do), nato dir_colors bo delovalo, Kljub vsemu).

Pa poglejmo pobliže

Da bi ugotovili, katera barvna shema povzroča upočasnitev, smo ustvarili poskusno okolje:

$ 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 sekunde za 10 datotek, ni zelo dobro.

Mimogrede, potrebujemo zastavo --color=always: čeprav se obrača na ls --color=autoVendar ls zazna, ko ni povezan s terminalom (npr. po cevi ali s preusmeritvijo izhoda) in onemogoči barvanje, če je nastavljeno auto. Pameten tip.

Kaj torej traja tako dolgo? Pogledali smo s 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
[...]

Vau: 10 klicev lstat(), 10 klicev getxattr() (ki vsi ne uspejo, ker naše okolje nima atributov, ki jih išče ls), 10 klicev capget().

Vsekakor se da to optimizirati.

Atribut zmogljivosti? ne

Po nasvetu napaka izpred 10 let, smo poskušali onemogočiti preverjanje atributov Zmogljivosti:

$ 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

Vau, do 8 sekund pospeška! Znebili smo se vseh tistih dragih klicev getxattr(), in izzivi capget() tudi izginilo, super.

Še vedno pa so ti nadležni klici lstat(), Čeprav…

Koliko rožic potrebuješ?

Zato smo vzeli pobližje LS_COLORS.

Najprej smo preprosto onemogočili to spremenljivko:

$ 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

Kaj!?! Še 13 sekund?

Izkazalo se je, da ko spremenljivka okolja LS_COLORS samo eden od njegovih elementov ni opredeljen ali manjka <type>=color:, privzeto uporablja vgrajeno bazo podatkov in še vedno uporablja barve. Torej, če želite onemogočiti barvanje za določeno vrsto datoteke, jo morate preglasiti z <type>=: ali <type> 00 v datoteki DIR_COLORS.

Po številnih poskusih in napakah smo naše iskanje zožili na tole:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

ki je zapisan kot

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

To pomeni: ne barvajte datotek po atributih. Zmogljivosti, ampak po delih setuid/setgid, niti z zastavica izvedljivosti.

Pospešimo ls

In če ne opravite nobenega od teh pregledov, potem klici lstat() izginejo, zdaj pa je povsem druga stvar:

$ 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 sekunde na seznamu 10 datotek, rekord.

Postavitev Sherlocka

Od 13 sekund s privzetimi nastavitvami do 0,3 sekunde z manjšimi prilagoditvami LS_COLORS pomeni 40-kratni pospešek zaradi odsotnosti setuid / setgid in barvne izvršljive datoteke. Ni tako velika izguba.

Seveda je to zdaj konfigurirano v Sherlocku za vsakega uporabnika.

Če pa želite vrniti barvo, se lahko preprosto vrnete na privzete nastavitve:

$ unset LS_COLORS

Toda v imenikih z veliko datotekami ne pozabite skuhati kave, medtem ko teče ls.

Vir: www.habr.com

Dodaj komentar