Quando una variabile d'ambiente accelera il processo di 40 volte

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ì, l'eseguibile legge il file di configurazione per creare una variabile di ambiente, che ls poi utilizza (e se non conosci i file porta (fare), quindi dir_colors funzionerà, Nonostante tutto).

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 a ls --color=automa ls rileva quando non è connesso a un terminale (ad esempio tramite pipe o con reindirizzamento dell'output) e disabilita la colorazione se impostato su auto. 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 bug di 10 anni fa, abbiamo provato a disabilitare il controllo degli attributi funzionalità:

$ 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. funzionalità, ma poco a poco setuid/setgid, né da flag di eseguibilità.

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

Aggiungi un commento