Oggi vogliamo parlare di alcuni degli ultimi aggiornamenti al sistema Sherlock [questo è un cluster ad alte prestazioni presso l'Università di Stanford - ca. trans.], che accelera notevolmente l'elenco dei file nelle directory con un gran numero di voci.
A differenza degli articoli normali, questo è più un rapporto interno su come lavoriamo regolarmente su Sherlock per mantenerlo funzionante al meglio per i nostri utenti. Speriamo di pubblicare altri articoli come questo in futuro.
Elencare molti file richiede tempo
Tutto è iniziato con una domanda di supporto tecnico da parte di un utente. Ha segnalato il problema dell'esecuzione ls
richiede alcuni minuti in una directory con oltre 15 voci $SCRATCH
[directory per i file temporanei - ca. sentiero].
Migliaia di file in una directory di solito rappresentano un peso per il file system e non sono assolutamente consigliati. L'utente lo sapeva e ha ammesso che non andava bene, ma ha detto che l'elenco era 1000 volte più veloce sul suo laptop rispetto a Sherlock. Naturalmente, questo ci ha ferito. Quindi abbiamo guardato più in profondità.
Perché sembra carino
Abbiamo esaminato cosa fa effettivamente ls
quando si elenca una directory e perché il processo richiede così tanto tempo. Sulla maggior parte delle distribuzioni moderne ls
per impostazione predefinita funziona come ls --color=auto
, perché a tutti piacciono i colori.
Ma i colori meravigliosi hanno un prezzo: per ogni file ls
deve ottenere informazioni sul tipo di file, i suoi permessi, flag, attributi estesi e simili per selezionare il colore appropriato.
Una soluzione semplice al problema è disabilitare del tutto il colore in ls, ma immagina l'indignazione degli utenti. In nessun caso bisogna togliere la resa cromatica, non siamo dei mostri.
Quindi abbiamo guardato più in profondità. ls
voci di colori tramite variabile di ambiente LS_COLORS
, che è impostato dircolors(1)
in base al file di configurazione dir_colors(5)
. Sì,
Diamo uno sguardo più da vicino
Per determinare quale combinazione di colori causa il rallentamento, abbiamo creato un ambiente sperimentale:
$ 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 secondi per 10 file, non molto buono.
A proposito, abbiamo bisogno di una bandiera
--color=always
: anche se si rivolge als --color=auto
mals
rileva quando non è connesso a un terminale (ad esempio tramite pipe o con reindirizzamento dell'output) e disabilita la colorazione se impostato suauto
. Ragazzo intelligente.
Allora perché ci vuole così tanto tempo? Abbiamo guardato con 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
[...]
Wow: 10 chiamate lstat()
, 10 chiamate getxattr()
(che falliscono tutti perché il nostro ambiente non ha gli attributi che ls sta cercando), 10 chiamate capget()
.
Sicuramente questo può essere ottimizzato.
Attributo di capacità? No
Seguendo il consiglio
$ 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
Wow, fino a 8 secondi di accelerazione! Ci siamo sbarazzati di tutte quelle chiamate costose getxattr()
e sfide capget()
scomparso anche lui, fantastico.
Ma ci sono ancora queste chiamate fastidiose lstat()
, Sebbene…
Di quanti fiori hai bisogno?
Pertanto, abbiamo dato un'occhiata più da vicino LS_COLORS
.
Per prima cosa abbiamo semplicemente disabilitato questa variabile:
$ 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
Che cosa!?! Ancora 13 secondi?
Si scopre che quando la variabile di ambiente LS_COLORS
solo uno dei suoi elementi non è definito o manca <type>=color:
, utilizza il database integrato per impostazione predefinita e utilizza ancora i colori. Pertanto, se desideri disabilitare la colorazione per un determinato tipo di file, devi sovrascriverla con <type>=:
o <type> 00
in archivio DIR_COLORS
.
Dopo molti tentativi ed errori, abbiamo ristretto la nostra ricerca a questo:
EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00
che è scritto come
LS_COLORS='ex=00:su=00:sg=00:ca=00:'
Ciò significa: non colorare i file per attributo.
, né da
Acceleriamo ls
E se non fai nessuno di questi controlli, allora chiama lstat()
scomparire, e ora è una questione completamente diversa:
$ 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 secondi su un elenco di 10 file, un record.
Incastrare Sherlock
Da 13 secondi con impostazioni predefinite a 0,3 secondi con piccole modifiche LS_COLORS
significa un'accelerazione di 40 volte dovuta all'assenza setuid
/ setgid
e file eseguibili colorati. Non è una perdita così grande.
Naturalmente, questo è ora configurato in Sherlock per ciascun utente.
Ma se vuoi ripristinare la colorazione, puoi semplicemente ripristinare le impostazioni predefinite:
$ unset LS_COLORS
Ma poi nelle directory con molti file, assicurati di preparare il caffè mentre è in esecuzione ls
.
Fonte: habr.com