Cando unha variable de ambiente acelera o proceso 40 veces

Hoxe queremos falar sobre algunhas das últimas actualizacións do sistema Sherlock [este é un clúster de alto rendemento na Universidade de Stanford - aprox. trans.], que aceleran significativamente a listaxe de ficheiros en directorios cun gran número de entradas.

A diferenza dos artigos habituais, este é máis un informe de información privilegiada sobre como traballamos regularmente en Sherlock para que este funcione ao máximo para os nosos usuarios. Esperamos publicar máis artigos coma este no futuro.

Listar moitos ficheiros leva tempo

Todo comezou cunha pregunta de soporte técnico dun usuario. Denunciaba o problema que supón a execución ls leva uns minutos nun directorio con máis de 15 entradas $SCRATCH [directorio para ficheiros temporais - aprox. carril].

Miles de ficheiros nun directorio adoitan representar unha carga para o sistema de ficheiros e definitivamente non se recomenda. O usuario sabía isto e admitiu que non era bo, pero mencionou que a lista era 1000 veces máis rápida no seu portátil que Sherlock. Por suposto, isto doeunos. Así que miramos máis a fondo.

Porque ten boa pinta

Miramos o que fai realmente ls ao listar un directorio e por que o proceso leva tanto tempo. Na maioría das distribucións modernas ls por defecto execútase como ls --color=auto, porque a todo o mundo lle gustan as cores.

Pero as fermosas cores teñen un prezo: por cada arquivo ls debe obter información sobre o tipo de ficheiro, os seus permisos, bandeiras, atributos estendidos e similares para seleccionar a cor adecuada.

Unha solución sinxela ao problema é desactivar a cor en ls por completo, pero imaxina a indignación dos usuarios. En ningún caso debes quitar a saída da cor, non somos monstros.

Así que miramos máis a fondo. ls entradas de cores a través da variable de ambiente LS_COLORS, que se establece dircolors(1) baseado no ficheiro de configuración dir_colors(5). Si, o executable le o ficheiro de configuración para crear unha variable de ambiente, que ls utiliza entón (e se non sabe sobre ficheiros porta (facer), despois dir_colors vai funcionar, A pesar de todo).

Vexamos máis de cerca

Para determinar que esquema de cores provoca a desaceleración, creamos un ambiente 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 segundos para 10 ficheiros, non moi bo.

Por certo, necesitamos unha bandeira --color=always: aínda que recorre a ls --color=autoPero ls detecta cando non está conectado a un terminal (por exemplo, por tubo ou con redirección de saída) e desactiva a cor se se establece en auto. Mozo intelixente.

Entón, que leva tanto tempo? Miramos con 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
[...]

Guau: 10 chamadas lstat(), 10 chamadas getxattr() (que todos fallan porque o noso entorno non ten os atributos que ls busca), 10 chamadas capget().

Seguramente isto pódese optimizar.

Atributo de capacidades? non

Seguindo consellos erro de hai 10 anos, tentamos desactivar a comprobación de atributos capacidades:

$ 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

Vaia, ata 8 segundos de aceleración! Libramos todas esas chamadas caras getxattr(), e retos capget() tamén desapareceu, xenial.

Pero aínda hai estas molestas chamadas lstat(), Aínda que…

Cantas flores necesitas?

Por iso, fixemos unha ollada máis atenta LS_COLORS.

Primeiro simplemente desactivamos esta 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

Que!?! Aínda quedan 13 segundos?

Acontece que cando a variable de ambiente LS_COLORS só un dos seus elementos non está definido ou falta <type>=color:, usa a base de datos integrada por defecto e aínda usa cores. Polo tanto, se queres desactivar a colorización para un determinado tipo de ficheiro, debes anulalo <type>=: ou <type> 00 en arquivo DIR_COLORS.

Despois de moitos intentos e erros, reducimos a nosa busca a isto:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

que se escribe como

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

Isto significa: non colorear os ficheiros por atributos. capacidades, pero pouco a pouco setuid/setgid, nin por bandeira de executabilidade.

Aceleramos ls

E se non fai ningunha destas comprobacións, entón chama lstat() desaparecer, e agora é unha cuestión completamente diferente:

$ 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 segundos nunha lista de 10 ficheiros, un rexistro.

Configurando Sherlock

Desde 13 segundos coa configuración predeterminada ata 0,3 segundos con pequenos axustes LS_COLORS significa unha aceleración de 40 veces debido á ausencia setuid / setgid e ficheiros executables de cores. Non é unha perda tan grande.

Por suposto, agora está configurado en Sherlock para cada usuario.

Pero se queres devolver a cor, simplemente podes volver á configuración predeterminada:

$ unset LS_COLORS

Pero despois, nos directorios con moitos ficheiros, asegúrate de preparar café mentres está en execución ls.

Fonte: www.habr.com

Engadir un comentario