Quan una variable d'entorn accelera el procés 40 vegades

Avui volem parlar d'algunes de les últimes actualitzacions del sistema Sherlock [es tracta d'un clúster d'alt rendiment a la Universitat de Stanford: aprox. trans.], que acceleren significativament la llista de fitxers en directoris amb un gran nombre d'entrades.

A diferència dels articles habituals, aquest és més un informe d'informació privilegiada sobre com treballem regularment a Sherlock per mantenir-lo funcionant al màxim per als nostres usuaris. Esperem poder publicar més articles com aquest en el futur.

Llistar molts fitxers requereix temps

Tot va començar amb una pregunta d'assistència tècnica d'un usuari. Va informar del problema que l'execució ls triga uns minuts en un directori amb més de 15 entrades $SCRATCH [directori per a fitxers temporals - aprox. carril].

Milers de fitxers en un directori solen suposar una càrrega per al sistema de fitxers i definitivament no es recomana. L'usuari ho sabia i va admetre que no era bo, però va esmentar que la llista era 1000 vegades més ràpida al seu ordinador portàtil que Sherlock. Això sí, això ens va fer mal. Així que vam mirar més a fons.

Perquè es veu bé

Vam mirar què fa realment ls en llistar un directori i per què el procés triga tant. A la majoria de distribucions modernes ls per defecte s'executa com ls --color=auto, perquè a tothom li agraden els colors.

Però els colors bonics tenen un preu: per a cada fitxer ls ha d'obtenir informació sobre el tipus de fitxer, els seus permisos, banderes, atributs ampliats i similars per seleccionar el color adequat.

Una solució senzilla al problema és desactivar el color a ls per complet, però imagineu-vos la indignació dels usuaris. En cap cas hauríeu de treure la sortida del color, no som monstres.

Així que vam mirar més a fons. ls entrades de colors mitjançant variable d'entorn LS_COLORS, que està establert dircolors(1) basat en el fitxer de configuració dir_colors(5)... Sí, l'executable llegeix el fitxer de configuració per crear una variable d'entorn, que després utilitza (i si no coneixeu els fitxers porta (fer), després dir_colors treballarà, Malgrat tot).

Fem una ullada més de prop

Per determinar quina combinació de colors provoca la desacceleració, hem creat un entorn 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 segons per a 10 fitxers, no molt bo.

Per cert, necessitem una bandera --color=always: encara que recorre a ls --color=autoSinó ls detecta quan no està connectat a un terminal (per exemple, per canonada o amb redirecció de sortida) i desactiva el color si s'estableix a auto. Paio intel·ligent.

Aleshores, què triga tant? Hem mirat amb 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 trucades lstat(), 10 trucades getxattr() (que fallen tots perquè el nostre entorn no té els atributs que ls busca), 10 trucades capget().

Segurament això es pot optimitzar.

Atribut de capacitats? No

Seguint consells error de fa 10 anys, hem intentat desactivar la comprovació d'atributs capacitats:

$ 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

Vaja, fins a 8 segons d'acceleració! Ens vam desfer de totes aquelles trucades cares getxattr(), i reptes capget() també va desaparèixer, genial.

Però encara hi ha aquestes trucades molestes lstat(), tot i que…

Quantes flors necessites?

Per tant, hem fet una ullada més de prop LS_COLORS.

Primer simplement vam desactivar aquesta variable:

$ 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

Què!?! Encara queden 13 segons?

Resulta que quan la variable d'entorn LS_COLORS només un dels seus elements no està definit o falta <type>=color:, utilitza la base de dades integrada per defecte i encara utilitza colors. Per tant, si voleu desactivar la coloració per a un tipus de fitxer determinat, heu de substituir-lo <type>=: o <type> 00 a l'arxiu DIR_COLORS.

Després de moltes proves i errors, hem reduït la nostra cerca a això:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

que s'escriu com

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

Això vol dir: no acolorir els fitxers per atribut. capacitats, però a poc a poc setuid/setgid, ni per bandera d'executabilitat.

Accelerem ls

I si no feu cap d'aquestes comprovacions, truqueu lstat() desaparèixer, i ara és una qüestió completament diferent:

$ 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 segons en una llista de 10 fitxers, un rècord.

Configurant Sherlock

Des de 13 segons amb la configuració predeterminada fins a 0,3 segons amb ajustos menors LS_COLORS significa una acceleració de 40 vegades a causa de l'absència setuid / setgid i fitxers executables de colors. No és una pèrdua tan gran.

Per descomptat, això ara està configurat a Sherlock per a cada usuari.

Però si voleu tornar el color, simplement podeu tornar a la configuració predeterminada:

$ unset LS_COLORS

Però després, als directoris amb molts fitxers, assegureu-vos de preparar cafè mentre s'està executant ls.

Font: www.habr.com

Afegeix comentari