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. per.], que acelera enormemente la lista de archivos en directorios con una gran cantidad de entradas.

A diferencia de los artículos normales, este es más un informe interno sobre cómo Sherlock trabaja regularmente para mantenerlo de la mejor manera posible para nuestros usuarios. Esperamos publicar más artículos de este tipo en el futuro.

Listar muchos archivos lleva tiempo


Todo comenzó con una pregunta de soporte técnico del usuario. Informó un problema de que ejecutar ls tomó varios minutos en un directorio con más de 15,000 entradas en $SCRATCH [directorio para archivos temporales - aprox. trans.].

Miles de archivos en un directorio generalmente crean dificultades para el sistema de archivos y esto definitivamente no se recomienda. El usuario lo sabía y admitió que no era bueno, pero mencionó que el listado en su computadora portátil era 1000 veces más rápido que en Sherlock. Por supuesto, nos golpeó. Por lo tanto, miramos más profundo.

Porque se ve hermosa


Observamos lo que realmente hace ls al enumerar un directorio y por qué el proceso lleva tanto tiempo. En la mayoría de las distribuciones modernas, ls predeterminado en ls --color=auto , porque a todos les gusta el color.

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

Una de las soluciones simples al problema es deshabilitar el color en ls por completo, pero imagine la indignación de los usuarios. En ningún caso puedes tomar la salida de color, no somos monstruos.

Por lo tanto, miramos más profundo. ls pinta los registros a través de la LS_COLORS entorno LS_COLORS , que dircolors(1) establece en función del archivo de configuración dir_colors(5) . Sí, el ejecutable lee el archivo de configuración para crear una variable de entorno que luego utiliza (y si no conoce los archivos de la puerta (do), dir_colors funcionará , pase lo que pase).

Entenderemos con más detalle


Para determinar cuál de los esquemas de coloración causa una 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,000 archivos, no muy bueno.
Por cierto, necesitamos el indicador --color=always : aunque cambia a ls --color=auto , pero ls detecta cuándo no está conectado al terminal (por ejemplo, a través de un canal o con redirección de salida) y desactiva el color si está configurado en auto . Chico inteligente
Entonces, ¿qué lleva tanto tiempo? Lo 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 [...] 

Wow: 10,000 llamadas a lstat() , 10,000 llamadas a getxattr() (que todos fallan porque en nuestro entorno no hay atributos que ls busque), 10,000 llamadas a capget() .

Seguramente esto se puede optimizar.

Atributo de capacidades No


Siguiendo el consejo de un error hace 10 años , intentamos desactivar la comprobación del atributo de 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 

¡Guau, aceleración de hasta 8 segundos! Nos deshicimos de todas estas costosas llamadas getxattr() , y las llamadas capget() también desaparecieron, genial.

Pero aún así estas molestas llamadas a lstat() permanecieron, aunque ...

¿Cuántas flores necesitas?


Por lo tanto, examinamos LS_COLORS con más detalle.

Primero, simplemente desactivaron 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: o = 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

 $ tiempo ls --color = siempre $ SCRATCH / dont |  wc -l
 10,000

 0m13.037s reales
 usuario 0m0.077s
 sys 0m1.092s 

¿Qué? ¿Todavía 13 segundos?

Resulta que cuando la LS_COLORS entorno LS_COLORS no LS_COLORS definida o si solo falta uno de sus elementos <type>=color: usa la base de datos incorporada de manera predeterminada y aún usa colores. Por lo tanto, si desea deshabilitar la coloración para un tipo de archivo específico, debe anularlo con <type>=: o <type> 00 en el archivo DIR_COLORS .

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

 EXEC 00 SETUID 00 SETGID 00 CAPABILITY 00 

lo que está escrito como

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

Esto significa: no coloree los archivos ni por las capacidades atrubut, ni por los bits setuid/setgid , ni por el indicador ejecutable .

Acelerando ls


Y si no realiza ninguna de estas comprobaciones, las llamadas a lstat() desaparecen, 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,000 archivos, un registro.

Configurar Sherlock


De 13 segundos con la configuración predeterminada a 0.3 segundos con una configuración pequeña LS_COLORS significa una aceleración de 40 veces debido a la falta de setuid / setgid y archivos ejecutables de colores. No es una gran pérdida.

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

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

 $ unset LS_COLORS 

Pero luego, en los directorios con una gran cantidad de archivos, asegúrese de preparar café mientras ls está funcionando.

Source: https://habr.com/ru/post/450806/


All Articles