Cuando una variable de entorno acelera el proceso 40 veces

Hoy queremos hablar sobre algunas de las últimas actualizaciones del sistema Sherlock [este es un clúster de alto rendimiento en la Universidad de Stanford, aprox. trans.], que acelera significativamente la lista de archivos en directorios con una gran cantidad de entradas.

A diferencia de los artículos habituales, este es más bien un informe interno sobre cómo trabajamos regularmente en Sherlock para que siga funcionando de la mejor manera para nuestros usuarios. Esperamos publicar más artículos como este en el futuro.

Listar muchos archivos lleva tiempo

Todo comenzó con una pregunta de soporte técnico de un usuario. Informó el problema que la ejecución ls tarda unos minutos en un directorio con más de 15 entradas en $SCRATCH [directorio para archivos temporales - aprox. carril].

Miles de archivos en un directorio suelen suponer una carga para el sistema de archivos y definitivamente no se recomienda. El usuario lo sabía y admitió que no era bueno, pero mencionó que el listado era 1000 veces más rápido en su computadora portátil que Sherlock. Por supuesto, esto nos duele. Entonces miramos más profundamente.

Porque se ve bien

Observamos lo que realmente hace. ls al incluir un directorio y por qué el proceso lleva tanto tiempo. En la mayoría de las distribuciones modernas ls por defecto se ejecuta como ls --color=auto, porque a todos les gustan los colores.

Pero los colores bonitos tienen un precio: por cada archivo ls Debe obtener información sobre el tipo de archivo, sus permisos, banderas, atributos extendidos y similares para poder seleccionar el color apropiado.

Una solución sencilla al problema es desactivar por completo el color en ls, pero imagine la indignación de los usuarios. Bajo ninguna circunstancia debes quitarle la salida de color, no somos monstruos.

Entonces miramos más profundamente. ls entradas de colores a través de variable de entorno LS_COLORS, que se establece dircolors(1) basado en el archivo de configuración dir_colors(5). Si el ejecutable lee el archivo de configuración para crear una variable de entorno, que luego usa (y si no sabes acerca de archivos Por (hacer), luego dir_colors trabajará, A pesar de todo).

Miremos más de cerca

Para determinar qué combinación de colores causa la desaceleración, creamos un entorno 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 archivos, no muy bueno.

Por cierto, necesitamos una bandera. --color=always: aunque se vuelve hacia ls --color=autoSino ls detecta cuando no está conectado a un terminal (por ejemplo, por tubería o con redirección de salida) y desactiva el color si se establece en auto. Chico inteligente.

Entonces, ¿por qué estás tardando tanto? 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
[...]

Vaya: 10 llamadas lstat(), 10 llamadas getxattr() (todos fallan porque nuestro entorno no tiene los atributos que ls busca), 10 llamadas capget().

Seguramente esto se puede optimizar.

¿Atributo de capacidades? No

Siguiendo consejos error de hace 10 años, intentamos deshabilitar la verificació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

¡Vaya, hasta 8 segundos de aceleración! Nos deshicimos de todas esas costosas llamadas. getxattr()y desafíos capget() Desapareció también, genial.

Pero todavía existen estas llamadas molestas. lstat(), A pesar de…

¿Cuántas flores necesitas?

Por lo tanto, echamos un vistazo más de cerca. LS_COLORS.

Primero simplemente deshabilitamos 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

¡¿¡Qué!?! ¿Aún quedan 13 segundos?

Resulta que cuando la variable de entorno LS_COLORS sólo uno de sus elementos no está definido o falta <type>=color:, utiliza la base de datos incorporada de forma predeterminada y aún usa colores. Entonces, si desea deshabilitar la coloración para un determinado tipo de archivo, debe anularla con <type>=: o <type> 00 en archivo DIR_COLORS.

Después de muchas pruebas y errores, limitamos nuestra búsqueda a esto:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

que se escribe como

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

Esto significa: no colorear archivos por atributo. capacidades, pero poco a poco setuid/setgid, ni por bandera de ejecutabilidad.

aceleramos ls

Y si no haces ninguna de estas comprobaciones, entonces llama lstat() desaparecer, y ahora es un asunto 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 en una lista de 10 archivos, un récord.

Preparando a Sherlock

Desde 13 segundos con la configuración predeterminada hasta 0,3 segundos con ajustes menores LS_COLORS significa una aceleración de 40 veces debido a la ausencia setuid / setgid y archivos ejecutables de colores. No es una pérdida tan grande.

Por supuesto, esto ahora está configurado en Sherlock para cada usuario.

Pero si desea devolver el color, simplemente puede volver a la configuración predeterminada:

$ unset LS_COLORS

Pero luego, en directorios con muchos archivos, asegúrese de preparar café mientras se está ejecutando. ls.

Fuente: habr.com

Añadir un comentario