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.