Cuando una variable de entorno acelera el proceso 40 veces

Hoy queremos hablar sobre algunas de las últimas actualizaciones del sistema Sherlock [un clúster de alto rendimiento de la Universidad de Stanford - nota del traductor], que aceleran significativamente el listado de archivos en directorios con un gran número de entradas.

A diferencia de los artículos habituales, esto es más bien un informe interno sobre cómo se lleva a cabo el trabajo regular en Sherlock para mantenerlo en óptimas condiciones para nuestros usuarios. Esperamos publicar más artículos como este en el futuro.

Listar muchos archivos lleva tiempo

Todo comenzó con una consulta al soporte técnico por parte de un usuario. Informó sobre un problema en el que la ejecución Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. toma varios minutos en un directorio con más de 15,000 entradas en $SCRATCH [directorio para archivos temporales - nota del traductor].

Miles de archivos en un solo directorio generalmente generan dificultades para el sistema de archivos y definitivamente no se recomienda. El usuario era consciente de esto y reconoció que no era bueno, pero mencionó que en su portátil el listado se realiza mil veces más rápido que en Sherlock. Por supuesto, eso nos afectó. Así que investigamos más a fondo.

Porque ls se ve bonito

Examinamos qué es lo que realmente hace Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. al listar un directorio, y por qué el proceso lleva tanto tiempo. En la mayoría de las distribuciones modernas Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. por defecto se ejecuta como ls --color=auto, porque a todos les gusta el color.

Pero los colores bonitos tienen su precio: para cada archivo Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. se debe obtener información sobre el tipo de archivo, sus permisos, banderas, atributos extendidos, etc., para elegir el color correspondiente.

Una de las soluciones simples al problema es desactivar el color en ls por completo, pero imaginen la indignación de los usuarios. De ninguna manera vamos a eliminar la salida colorida, no somos monstruos.

Así que investigamos más a fondo. Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. pinta las entradas a través de la variable de entorno LS_COLORS, que es definida por dircolors(1) basándose en el 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 ls (y si no sabes sobre los archivos door (do), entonces dir_colors , pase lo que pase). en casos más complejos como un ataque de inyección de procesos. Por lo tanto, la nueva firewall aún no puede tomar medidas por sí misma para proteger la red; solo puede enviar notificaciones al administrador.Profundicemos un poco más

Para determinar cuál de los esquemas de coloración está causando la ralentización, creamos un entorno experimental:

$ mkdir $SCRATCH/dont $ touch $SCRATCH/dont/{1..10000} # no lo hagas en casa! $ time ls --color=always $SCRATCH/dont | wc -l 10000real 0m12.758s user 0m0.104s sys 0m0.699s

$ 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 bien.

Por cierto, se necesita una bandera --color=always: aunque se convierte en ls --color=auto, pero Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual. detecta cuando no está conectado a un terminal (por ejemplo, a través de un canal o con redirección de salida) y desactiva el color si se establece el valor auto. Chaval inteligente.

¿Entonces qué está tomando tanto tiempo? Miramos con strace:

$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% tiempo     segundos  usecs/call     llamadas    errores 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
[...]

Increíble: 10,000 llamadas lstat(), 10,000 llamadas getxattr() (que todas fallan porque no hay atributos que busca ls en nuestro entorno), 10,000 llamadas capget().

Seguramente esto se puede optimizar.

¿Atributo de capacidades? No.

Siguiendo los consejos un bug de hace 10 años, intentamos desactivar la verificación de atributo capabilities:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% tiempo     segundos  usecs/call     llamadas    errores 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, aceleración a 8 segundos! Nos deshicimos de todas esas llamadas costosas getxattr(), y las llamadas capget() también desaparecieron, excelente.

Pero aún quedan esas molestas llamadas lstat(), aunque...

¿Cuántos colores se necesitan?

Por eso examinamos más a fondo LS_COLORS.

Primero 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

¿Qué!?! ¿Todavía 13 segundos?

Resulta que cuando la variable de entorno LS_COLORS no está definida o falta sólo uno de sus elementos =color:, por defecto utiliza la base de datos integrada y sigue utilizando colores. Por lo tanto, si deseas desactivar la coloración para un tipo de archivo específico, necesitas sobrescribirla con =: o 00 en el archivo DIR_COLORS.

Después de muchos intentos y errores, restringimos la 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 los archivos ni por atributo capabilities, ni por bits setuid/setgid, ni por el flag de ejecutabilidad.

Acelerando Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual.

Y si no realizas ninguna de estas verificaciones, entonces las llamadas lstat() desaparecen, y ahora es algo 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, récord.

Configurando Sherlock

Desde 13 segundos con la configuración por defecto a 0,3 segundos con una pequeña configuración LS_COLORS significa una aceleración de 40 veces gracias a la falta de setuid / setgid y archivos ejecutables coloreados. No es una gran pérdida.

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

Pero si deseas recuperar el color, puedes simplemente volver a la configuración predeterminada:

$ unset LS_COLORS

Pero entonces, en directorios con muchos archivos, asegúrate de preparar café mientras trabaja. Muestra el contenido del directorio. Si no se proporciona una ruta, se muestra el contenido del directorio actual..

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster