Kiam mediovariablo plirapidigas la procezon je 40 fojojn

Hodiaŭ ni volas paroli pri kelkaj el la plej novaj ĝisdatigoj al la Sherlock-sistemo [ĉi tio estas alt-efikeca areto en Universitato Stanford - ĉ. trans.], kiu signife plirapidigas listigon de dosieroj en dosierujoj kun granda nombro da enskriboj.

Male al regulaj artikoloj, ĉi tio estas pli de interna raporto pri kiel ni regule laboras pri Sherlock por ke ĝi funkcias plej bone por niaj uzantoj. Ni esperas publikigi pli da tiaj artikoloj estonte.

Listigi multajn dosierojn bezonas tempon

Ĉio komenciĝis per teknika subtena demando de uzanto. Li raportis la problemon, ke la ekzekuto ls prenas kelkajn minutojn en dosierujo kun pli ol 15 enskriboj $SCRATCH [dosierujo por provizoraj dosieroj - ĉ. leno].

Miloj da dosieroj en unu dosierujo kutime prezentas ŝarĝon al la dosiersistemo kaj certe ne estas rekomenditaj. La uzanto sciis ĉi tion kaj konfesis, ke ĝi ne estas bona, sed menciis, ke la listo estis 1000 fojojn pli rapida en sia tekkomputilo ol Sherlock. Kompreneble, ĉi tio doloris nin. Do ni rigardis pli profunde.

Ĉar ls aspektas bela

Ni rigardis kion ĝi efektive faras ls kiam listigas dosierujon, kaj kial la procezo daŭras tiel longe. Sur plej modernaj distribuoj ls defaŭlte ĝi funkcias kiel ls --color=auto, ĉar ĉiuj ŝatas la kolorojn.

Sed belaj koloroj havas prezon: por ĉiu dosiero ls devas akiri informojn pri la dosiertipo, ĝiaj permesoj, flagoj, etenditaj atributoj kaj similaj por elekti la taŭgan koloron.

Unu simpla solvo al la problemo estas tute malŝalti koloron en ls, sed imagu la indignon de uzantoj. Neniam vi forprenu la kolorproduktaĵon, ni ne estas monstroj.

Do ni rigardis pli profunde. ls koloraj eniroj per mediovariablo LS_COLORS, kiu estas fiksita dircolors(1) surbaze de agorda dosiero dir_colors(5). Jes, la efektivigebla legas la agordan dosieron por krei mediovariablon, kiun ls tiam uzas (kaj se vi ne scias pri dosieroj pordo (do), tiam dir_koloroj funkcios, Malgraŭ ĉio).

Ni rigardu pli detale

Por determini kiu kolorskemo kaŭzas la malrapidiĝon, ni kreis eksperimentan medion:

$ 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 sekundoj por 10 dosieroj, ne tre bona.

Cetere, ni bezonas flagon --color=always: kvankam li turnas sin al ls --color=auto, sed ls detektas kiam ĝi ne estas konektita al terminalo (ekz. per pipo aŭ kun eliga redirekto) kaj malŝaltas kolorigon se agordita al auto. Saĝa ulo.

Kio do daŭras tiel longe? Ni rigardis kun 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 vokoj lstat(), 10 vokoj getxattr() (kiuj ĉiuj malsukcesas ĉar nia medio ne havas la atributojn, kiujn ls serĉas), 10 vokoj capget().

Verŝajne ĉi tio povas esti optimumigita.

Kapabloj atributo? Ne

Sekva konsilo cimo de antaŭ 10 jaroj, ni provis malŝalti atributan kontrolon Kapabloj:

$ 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

Ve, ĝis 8 sekundoj da akcelo! Ni forigis ĉiujn tiujn multekostajn vokojn getxattr(), kaj defioj capget() malaperis ankaŭ, bonega.

Sed ankoraŭ ekzistas ĉi tiuj ĝenaj vokoj lstat(), Kvankam…

Kiom da floroj vi bezonas?

Tial ni rigardis pli detale LS_COLORS.

Unue ni simple malŝaltis ĉi tiun variablon:

$ 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

Kio!?! Ĉu ankoraŭ 13 sekundoj?

Rezultas, ke kiam la medio variablo LS_COLORS nur unu el ĝiaj elementoj ne estas difinita aŭ mankas <type>=color:, ĝi uzas la enkonstruitan datumbazon defaŭlte kaj ankoraŭ uzas kolorojn. Do se vi volas malŝalti kolorigon por certa dosiertipo, vi devas anstataŭi ĝin per <type>=:<type> 00 en dosiero DIR_COLORS.

Post multe da provo kaj eraro, ni malvastigis nian serĉon al ĉi tio:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

kiu estas skribita kiel

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

Ĉi tio signifas: ne kolorigu dosierojn laŭ atributo. Kapabloj, sed iom post iom setuid/setgid, nek de flago de ekzekuto.

Ni rapidigas ls

Kaj se vi ne faras iun el ĉi tiuj kontroloj, tiam vokas lstat() malaperu, kaj nun estas tute alia afero:

$ 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 sekundoj en listo de 10 dosieroj, rekordo.

Starigante Sherlock

De 13 sekundoj kun defaŭltaj agordoj ĝis 0,3 sekundoj kun etaj alĝustigoj LS_COLORS signifas 40-oblan akcelon pro la foresto setuid / setgid kaj koloraj ruleblaj dosieroj. Ne tiom granda perdo.

Kompreneble, ĉi tio nun estas agordita en Sherlock por ĉiu uzanto.

Sed se vi volas redoni la kolorigon, vi povas simple reveni al la defaŭltaj agordoj:

$ unset LS_COLORS

Sed tiam ĉe dosierujoj kun multaj dosieroj, nepre preparu kafon dum ĝi funkcias ls.

fonto: www.habr.com

Aldoni komenton