Quando uma variável de ambiente acelera o processo em 40 vezes

Hoje queremos falar sobre algumas das atualizações mais recentes do sistema Sherlock [este é um cluster de alto desempenho da Universidade de Stanford - aprox. trans.], que acelera significativamente a listagem de arquivos em diretórios com um grande número de entradas.

Ao contrário dos artigos regulares, este é mais um relatório interno sobre como trabalhamos regularmente no Sherlock para mantê-lo funcionando da melhor forma para nossos usuários. Esperamos publicar mais artigos como este no futuro.

Listar muitos arquivos leva tempo

Tudo começou com uma pergunta de suporte técnico de um usuário. Ele relatou o problema que a execução ls leva alguns minutos em um diretório com mais de 15 entradas em $SCRATCH [diretório para arquivos temporários - aprox. faixa].

Milhares de arquivos em um diretório geralmente representam um fardo para o sistema de arquivos e definitivamente não são recomendados. O usuário sabia disso e admitiu que não era bom, mas mencionou que a listagem era 1000 vezes mais rápida em seu laptop do que em Sherlock. Claro, isso nos machucou. Então olhamos mais profundamente.

Porque parece legal.

Vimos o que ele realmente faz ls ao listar um diretório e por que o processo demora tanto. Na maioria das distribuições modernas ls por padrão ele é executado como ls --color=auto, porque todo mundo gosta das cores.

Mas belas cores têm um preço: para cada arquivo ls deve obter informações sobre o tipo de arquivo, suas permissões, sinalizadores, atributos estendidos e similares para selecionar a cor apropriada.

Uma solução simples para o problema é desativar completamente a cor em ls, mas imagine a indignação dos usuários. Sob nenhuma circunstância você deve retirar a saída colorida, não somos monstros.

Então olhamos mais profundamente. ls entradas de cores via variável de ambiente LS_COLORS, que está definido dircolors(1) baseado no arquivo de configuração dir_colors(5). Sim o executável lê o arquivo de configuração para criar uma variável de ambiente, que ls então usa (e se você não sabe sobre arquivos porta (fazer), então dir_colors vai funcionar, Apesar de tudo).

Vamos olhar mais de perto

Para determinar qual esquema de cores causa a lentidão, criamos um 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 arquivos, não muito bom.

A propósito, precisamos de uma bandeira --color=always: embora ele se volte para ls --color=automas ls detecta quando não está conectado a um terminal (por exemplo, por pipe ou com redirecionamento de saída) e desativa a coloração se definido como auto. Cara inteligente.

Então, por que está demorando tanto? Nós olhamos com 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
[...]

Uau: 10 ligações lstat(), 10 chamadas getxattr() (que falham porque nosso ambiente não possui os atributos que ls está procurando), 10 chamadas capget().

Certamente isso pode ser otimizado.

Atributo de capacidades? Não

Seguindo conselhos bug de 10 anos atrás, tentamos desabilitar a verificação 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

Uau, até 8 segundos de aceleração! Nos livramos de todas aquelas ligações caras getxattr()e desafios capget() desapareceu também, ótimo.

Mas ainda existem essas ligações irritantes lstat(), Embora…

Quantas flores você precisa?

Portanto, olhamos mais de perto LS_COLORS.

Primeiro, simplesmente desabilitamos esta variável:

$ 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

O que!?! Ainda 13 segundos?

Acontece que quando a variável de ambiente LS_COLORS apenas um de seus elementos não está definido ou está faltando <type>=color:, ele usa o banco de dados integrado por padrão e ainda usa cores. Portanto, se você deseja desativar a colorização para um determinado tipo de arquivo, é necessário substituí-lo por <type>=: ou <type> 00 no arquivo DIR_COLORS.

Depois de muitas tentativas e erros, restringimos nossa pesquisa a isto:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

que está escrito como

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

Isso significa: não colora os arquivos por atributo. capacidades, mas aos poucos setuid/setgid, nem por sinalizador de executabilidade.

Nós aceleramos ls

E se você não fizer nenhuma dessas verificações, então liga lstat() desaparecer, e agora é uma questão 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 em uma lista de 10 arquivos, um recorde.

Configurando Sherlock

13 segundos com configurações padrão para 0,3 segundos com pequenos ajustes LS_COLORS significa uma aceleração de 40 vezes devido à ausência setuid / setgid e arquivos executáveis ​​coloridos. Não é uma perda tão grande.

Claro, isso agora está configurado no Sherlock para cada usuário.

Mas se quiser retornar a coloração, você pode simplesmente retornar às configurações padrão:

$ unset LS_COLORS

Mas então, em diretórios com muitos arquivos, certifique-se de preparar o café enquanto ele estiver em execução ls.

Fonte: habr.com

Adicionar um comentário