Quando una variabile ambientale accelera il processo di 40 volte

Oggi vogliamo parlarvi di alcuni recenti aggiornamenti del sistema Sherlock [questo è un cluster ad alte prestazioni dell'Università di Stanford – nota dell'editore], che accelerano notevolmente l'elenco dei file in directory con un elevato numero di record.

A differenza degli articoli normali, questo è più un report interno su come viene eseguito il lavoro regolare su Sherlock per mantenerlo nelle migliori condizioni per i nostri utenti. Speriamo di pubblicare più articoli di questo tipo in futuro.

Elencare molti file richiede tempo

Tutto è iniziato con una domanda posta al supporto tecnico da un utente. Ha segnalato un problema: l'esecuzione ls richiede diversi minuti in una directory con più di 15.000 record in $SCRATCH [directory per file temporanei – nota dell'editore].

Migliaia di file in una directory di solito creano difficoltà per il file system e questo è decisamente sconsigliato. L'utente lo sapeva e riconosceva che non era una buona cosa, ma ha menzionato che sul suo laptop l'elenco viene eseguito 1000 volte più velocemente rispetto a Sherlock. Naturalmente, questo ci ha colpito. Così abbiamo approfondito.

Perché ls sembra bello

Abbiamo esaminato cosa fa realmente ls durante l'elenco del catalogo e perché il processo richiede così tanto tempo. Nella maggior parte delle distribuzioni moderne ls è eseguito di default come ls --color=auto, perché a tutti piacciono i colori.

Ma i bei colori hanno un costo: per ogni file ls deve ottenere informazioni sul tipo di file, le sue autorizzazioni, i flag, gli attributi estesi e simili, per scegliere il colore appropriato.

Una delle soluzioni semplici al problema è disattivare completamente il colore in ls, ma immaginate l'indignazione degli utenti. Non possiamo assolutamente rimuovere l'output a colori, non siamo dei mostri.

Quindi abbiamo approfondito. ls Evidenzia le voci tramite la variabile d'ambiente LS_COLORS, impostata da dircolors(1) sulla base del file di configurazione dir_colors(5). Sì,il file eseguibile legge il file di configurazione per creare la variabile d'ambiente, che poi viene utilizzata da ls (e se non conoscete i file door (do), allora dir_colors , a prescindere da tutto). funzioneràEsploriamo più in dettaglio

Per determinare quale schema di colorazione sta causando il rallentamento, abbiamo creato un ambiente sperimentale:

Per determinare quale schema di colorazione provoca un rallentamento, abbiamo creato un ambiente sperimentale:

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # non provateci a casa!
$ time ls --color=always $SCRATCH/dont | wc -l
10000

real    0m12.758s
user    0m0.104s
sys     0m0.699s

12,7 secondi per 10.000 file, non è molto buono.

A proposito, serve un flag --color=always: anche se si rende ls --color=auto, ma ls rileva quando non è collegato al terminale (ad esempio, tramite pipe o con reindirizzamento dell'output) e disabilita la colorazione se è impostato a auto. Bel colpo.

Allora, cosa ci mette così tanto? Abbiamo esaminato 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
[...]

Caspita: 10.000 chiamate lstat(), 10.000 chiamate getxattr() (che tutte falliscono perché nel nostro ambiente non ci sono attributi cercati da ls), 10.000 chiamate capget().

Sicuramente si può ottimizzare.

Attributo capabilities? No

Seguendo i suggerimenti di un bug di dieci anni fa, abbiamo provato a disabilitare il controllo dell'attributo capacità:

$ 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 totale

reale    0m8.160s
utente    0m0.115s
sys     0m0.961s

Wow, accelerazione a 8 secondi! Abbiamo rimosso tutte queste chiamate costose getxattr(), e le chiamate capget() sono scomparsi anche, ottimo.

Ma ci sono ancora queste fastidiose chiamate lstat(), anche se…

Quanti colori servono?

Quindi abbiamo esaminato più in dettaglio LS_COLORS.

Innanzitutto 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

Cosa!?! Ancora 13 secondi?

Si scopre che quando la variabile di ambiente LS_COLORS non è definita o manca solo uno dei suoi elementi =color:, utilizza per impostazione predefinita un database integrato e continua a utilizzare i colori. Pertanto, se desideri disabilitare la colorazione per un determinato tipo di file, devi sovrascriverlo con =: o 00 nel file DIR_COLORS.

Dopo molti tentativi e errori, abbiamo ristretto la ricerca a questo:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

che viene registrato come

LS_COLORS='ex=00:su=00:sg=00:ca=00:'

Questo significa: non colorare i file né per attributo capacità, né per bit setuid/setgid, né per il flag di esecuzione.

Acceleriamo ls

E se non facciamo nessuna di queste verifiche, allora le chiamate lstat() scompaiono, e ora è tutta un'altra storia:

$ 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 per un elenco di 10.000 file, un record.

Configuriamo Sherlock

Da 13 secondi con le impostazioni predefinite a 0,3 secondi con una piccola configurazione LS_COLORS significa un'accelerazione di 40 volte grazie all'assenza di setuid / setgid e dei file eseguibili colorati. Non è una grande perdita.

Certo, ora è configurato in Sherlock per ogni utente.

Ma se desideri ripristinare i colori, puoi semplicemente tornare alle impostazioni predefinite:

$ unset LS_COLORS

Ma allora, in directory con molti file, assicurati di prepararti un caffè mentre è in esecuzione ls.

Fonte: habr.com

Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster