Quando si esegue ls
senza argomenti, si aprirà semplicemente una directory, leggerà tutti i contenuti, li ordinerà e li stamperà.
Quando esegui ls *
, per prima cosa la shell si espande *
, il che è effettivamente lo stesso di quello che ha fatto il semplice ls
, crea un vettore argomento con tutti i file nella directory corrente e chiama ls
. ls
deve quindi elaborare quell'argomento vettore e per ogni argomento e chiama access(2)
¹ il file per verificarne l'esistenza. Quindi stamperà lo stesso output del primo (semplice) ls
. Sia l'elaborazione della shell del vettore di argomenti di grandi dimensioni ls
che la causa implicheranno probabilmente molta allocazione di memoria di piccoli blocchi, che può richiedere del tempo. Tuttavia, poiché non vi era poco sys
e user
il tempo, ma un sacco di real
tempo, la maggior parte del tempo sarebbe stato speso in attesa per il disco, invece di usare CPU a fare l'allocazione della memoria.
Ogni chiamata a access(2)
dovrà leggere l'inode del file per ottenere le informazioni sull'autorizzazione. Ciò significa che molte più letture e ricerche su disco rispetto alla semplice lettura di una directory. Non so quanto siano costose queste operazioni sul tuo GPFS, ma come il confronto a cui hai mostrato ls -l
che ha un tempo di esecuzione simile al caso jolly, il tempo necessario per recuperare le informazioni sull'inode sembra dominare. Se GPFS ha una latenza leggermente superiore rispetto al filesystem locale su ogni operazione di lettura, ci aspetteremmo che sia più pronunciato in questi casi.
La differenza tra il caso jolly e ls -l
del 50% potrebbe essere spiegata dall'ordinamento degli inode sul disco. Se gli inode fossero disposti in successione nello stesso ordine dei nomi dei file nella directory e ls -l
stat (2) ed i file in ordine di directory prima dell'ordinamento, ls -l
probabilmente leggerebbero la maggior parte degli inode in uno sweep. Con il carattere jolly, la shell ordinerà i nomi dei file prima di passarli a ls
, quindi ls
probabilmente leggerà gli inode in un ordine diverso, aggiungendo più movimento alla testa del disco.
Va notato che l' time
output non includerà il tempo impiegato dalla shell per espandere il carattere jolly.
Se vuoi davvero vedere cosa sta succedendo, usa strace(1)
:
strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *
e controlla quali chiamate di sistema vengono eseguite in ciascun caso.
¹ Non so se access(2)
viene effettivamente utilizzato o qualcos'altro come stat(2)
. Ma entrambi probabilmente richiedono una ricerca di inode (non sono sicuro access(file, 0)
che ignorerebbe una ricerca di inode.)
ls
quale può semplicemente chiedere al file system "quali sono i figli dell'inodepwd
" dovels *
deve chiedere "quali sono i bambini (e qual è il file) dell'inodea
" seguito da b, c, d, ecc. ecc. Una query contro molte.