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,
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 als --color=auto
Perols
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 enauto
. 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
$ 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.
, nin por
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