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
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 parals --color=auto
masls
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 comoauto
. 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
$ 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.
, nem por
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