Hoje queremos falar sobre algumas das atualizações mais recentes do sistema Sherlock [um cluster de alto desempenho da Universidade de Stanford — nota do tradutor], que aceleram significativamente o listagem de arquivos em diretórios com um grande número de registros.
Ao contrário de artigos comuns, este é mais um relatório interno sobre como o trabalho regular no Sherlock é realizado para mantê-lo em excelente forma para nossos usuários. Esperamos publicar mais artigos como este no futuro.
Listar muitos arquivos leva tempo.
Tudo começou com uma pergunta para o suporte técnico de um usuário. Ele relatou um problema em que a execução ls levava vários minutos em um diretório com mais de 15.000 registros em $SCRATCH [diretório para arquivos temporários — nota do tradutor].
Milhares de arquivos em um único diretório geralmente criam dificuldades para o sistema de arquivos, e isso definitivamente não é recomendado. O usuário sabia disso e reconheceu que não era bom, mas mencionou que em seu laptop a listagem era 1000 vezes mais rápida do que no Sherlock. Claro, isso nos incomodou. Portanto, fomos mais a fundo.
Porque o ls parece bonito.
Analisamos o que o ls realmente faz ao listar um diretório e por que o processo leva tanto tempo. Na maioria das distribuições modernas, ls é executado por padrão como ls --color=auto, porque todos gostam de cores.
Mas cores bonitas têm seu preço: para cada arquivo ls é necessário obter informações sobre o tipo de arquivo, suas permissões, flags, atributos estendidos e assim por diante, para escolher a cor apropriada.
Uma das soluções simples para o problema é desabilitar a cor no ls, mas imagine a indignação dos usuários. De forma alguma vamos retirar a saída colorida, não somos monstros.
Por isso, fomos mais a fundo. ls colore as entradas através da variável de ambiente LS_COLORS, que é definida por dircolors(1) com base no arquivo de configuração dir_colors(5).Sim, e se você não sabe sobre arquivos (do), então dir_colors , não importa o que aconteça.
Vamos analisar mais a fundo.
Para determinar qual dos esquemas de coloração está causando a lentidão, criamos um ambiente experimental:
$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # não tente isso em casa!
$ time ls --color=always $SCRATCH/dont | wc -l
10000
real 0m12.758s
user 0m0.104s
sys 0m0.699s12,7 segundos para 10.000 arquivos, não é muito bom.
Aliás, precisa da flag
--color=always: embora ele se refira als --color=auto, maslsdetecta quando não está conectado ao terminal (por exemplo, por um pipe ou com redirecionamento de saída) e desativa a coloração, se configuradoauto. Cara esperto.
Então, o que leva tanto tempo? Nós verificamos 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.000 chamadas lstat(), 10.000 chamadas getxattr() (que todas falham, porque em nosso ambiente não há atributos que o ls procura), 10.000 chamadas capget().
Com certeza isso pode ser otimizado.
Atributo capabilities? Não.
Seguindo as recomendações , tentamos desativar a verificação de atributo :
$ 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, aceleração para 8 segundos! Eliminamos todas essas chamadas caras getxattr(), e as chamadas capget() também desapareceram, ótimo.
Mas ainda restam essas chamadas incômodas lstat(), embora…
Quantas cores são necessárias?
Então analisamos mais de perto LS_COLORS.
Primeiro simplesmente desativamos essa 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 quê!?! 13 segundos ainda?
Aparentemente, quando a variável de ambiente LS_COLORS não está definida ou falta apenas um de seus elementos =color:, por padrão, utiliza o banco de dados embutido e ainda usa cores. Portanto, se você quiser desativar a coloração para um tipo específico de arquivo, você precisa sobrescrevê-la com =: ou 00 no arquivo DIR_COLORS.
Após muitas tentativas e erros, restringimos a busca para isso:
EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00que é escrito como
LS_COLORS='ex=00:su=00:sg=00:ca=00:' Isso significa: não colore arquivos nem por atributo , nem por bits , nem pelo .
Acelerando ls
E se nenhuma dessas verificações for feita, então as chamadas lstat() desaparecem, e agora é outra história:
$ 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.029s0,3 segundos na lista de 10.000 arquivos, um recorde.
Configurando Sherlock
De 13 segundos com configurações padrão para 0,3 segundos com uma pequena configuração LS_COLORS significa um aumento de 40 vezes devido à ausência de setuid / setgid e arquivos executáveis coloridos. Não é uma grande perda.
Claro, agora está configurado no Sherlock para cada usuário.
Mas se você quiser restaurar a coloração, pode simplesmente voltar às configurações padrão:
$ unset LS_COLORS Mas então, em diretórios com muitos arquivos, não esqueça de preparar um café enquanto isso acontece. ls.
Fonte: habr.com
