Hoje queremos falar sobre algumas das atualizações mais recentes do sistema Sherlock [este é um cluster de alto desempenho na Universidade de Stanford - aprox. por.], o que acelera bastante 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 o trabalho regular em Sherlock está em andamento, a fim de mantê-lo da melhor maneira possível para nossos usuários. Esperamos publicar mais artigos desse tipo no futuro.
Listar muitos arquivos leva tempo
Tudo começou com uma pergunta de suporte técnico do usuário. Ele relatou um problema que a execução de
ls
levou vários minutos em um diretório com mais de 15.000 entradas no diretório
$SCRATCH
[para arquivos temporários - aprox. trans.].
Milhares de arquivos em um diretório geralmente criam dificuldades para o sistema de arquivos e isso definitivamente não é recomendado. O usuário sabia disso e admitiu que não era bom, mas mencionou que a listagem em seu laptop é 1000 vezes mais rápida que em Sherlock. Claro, isso nos atingiu. Portanto, analisamos mais profundamente.
Porque ls está lindo
Vimos o que
ls
realmente faz ao listar um diretório e por que o processo leva tanto tempo. Na maioria das distribuições modernas,
ls
assume como padrão
ls --color=auto
, porque todo mundo gosta da cor.
Mas cores bonitas têm um preço: para cada arquivo, é necessário obter informações sobre o tipo de arquivo, suas permissões, sinalizadores, atributos avançados e similares, para selecionar a cor apropriada.
Uma das soluções simples para o problema é desativar totalmente a cor em ls, mas imagine a indignação dos usuários. Em nenhum caso você pode pegar a saída colorida, não somos monstros.
Portanto, analisamos mais profundamente.
ls
pinta os registros através da
LS_COLORS
ambiente
LS_COLORS
, que
dircolors(1)
define com base 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 ele usa (e se você não souber sobre os arquivos da
porta (do)), o dir_colors
funcionará , não importa o que aconteça.
Vamos entender com mais detalhes
Para determinar qual dos esquemas de colorização causa uma desaceleraçã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.000 arquivos, não muito bom.A propósito, precisamos do sinalizador --color=always
: embora ele se torne ls --color=auto
, mas ls
detecta quando não está conectado ao terminal (por exemplo, através de um canal ou com redirecionamento de saída) e desativa a coloração se estiver definido como auto
. Cara esperto.
Então, o que leva tanto tempo? 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.000 chamadas para
lstat()
, 10.000 chamadas para
getxattr()
(que todo mundo falha porque em nosso ambiente não há atributos que ls procura), 10.000 chamadas para
capget()
.
Certamente isso pode ser otimizado.
Atributo Recursos Não
Seguindo o conselho de um
bug há 10 anos , tentamos desativar a verificação do 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
Uau, aceleração de até 8 segundos! Nos livramos de todas essas
getxattr()
caras do
getxattr()
, e as chamadas do
capget()
também desapareceram, ótimo.
Mas ainda assim essas chamadas irritantes para
lstat()
continuaram ...
Quantas flores você precisa?
Portanto, examinamos
LS_COLORS
em mais detalhes.
Primeiro, eles simplesmente desativaram 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: ou = 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 = sempre $ SCRATCH / dont | wc -l
10.000
0m13.037s reais
usuário 0m0.077s
sys 0m1.092s
O que!?! Ainda 13 segundos?
Acontece que quando a
LS_COLORS
ambiente
LS_COLORS
não
LS_COLORS
definida ou se apenas um de seus elementos
<type>=color:
ausente, ele usa o banco de dados interno por padrão e ainda usa cores. Portanto, se você deseja desativar a coloração para um tipo de arquivo específico, é necessário substituí-lo por
<type>=:
ou
<type> 00
no arquivo
DIR_COLORS
.
Após várias tentativas e erros, restringimos nossa pesquisa a isso:
EXEC 00 SETUID 00 SETGID 00 CAPABILITY 00
o que está escrito como
LS_COLORS='ex=00:su=00:sg=00:ca=00:'
Isso significa: não pinte os arquivos pelos
recursos atrubut, pelos bits
setuid/setgid
ou pelo
sinalizador executável .
Acelerando ls
E se você não fizer nenhuma dessas verificações, as chamadas para
lstat()
desaparecem 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.000 arquivos, um registro.
Configurar Sherlock
De 13 segundos com configurações padrão a 0,3 segundos com uma configuração pequena
LS_COLORS
significa aceleração de 40 vezes devido à falta de
setuid
/
setgid
e arquivos executáveis coloridos. Não é uma perda tão grande.
Obviamente, agora isso está configurado no Sherlock para cada usuário.
Mas se você quiser retornar a coloração, basta voltar às configurações padrão:
$ unset LS_COLORS
Mas, em diretórios com um grande número de arquivos, faça café enquanto o
ls
estiver funcionando.