Lorsque vous exécutez ls
sans arguments, il suffit d'ouvrir un répertoire, de lire tout le contenu, de les trier et de les imprimer.
Lorsque vous exécutez ls *
, le shell se développe d'abord *
, ce qui est en fait le même que ce que le simple a ls
fait, construit un vecteur d'argument avec tous les fichiers du répertoire en cours et appelle ls
. ls
doit ensuite traiter ce vecteur d'argument et pour chaque argument, et appelle access(2)
¹ le fichier pour vérifier son existence. Ensuite, il imprimera la même sortie que la première (simple) ls
. Le traitement par le shell du grand vecteur d'arguments et ls
de celui-ci impliquera probablement beaucoup d'allocation de mémoire de petits blocs, ce qui peut prendre un certain temps. Cependant, comme il y avait peu sys
et le user
temps, mais beaucoup de real
temps, la plupart du temps aurait été passé à attendre pour le disque, plutôt que d' utiliser faire l' allocation de mémoire CPU.
Chaque appel à access(2)
devra lire l'inode du fichier pour obtenir les informations d'autorisation. Cela signifie beaucoup plus de lectures et de recherches sur disque que la simple lecture d'un répertoire. Je ne sais pas combien ces opérations coûtent sur votre GPFS, mais comme la comparaison que vous avez montrée ls -l
a un temps d'exécution similaire à celui du caractère générique, le temps nécessaire pour récupérer les informations d'inode semble dominer. Si GPFS a une latence légèrement plus élevée que votre système de fichiers local à chaque opération de lecture, nous nous attendons à ce qu'elle soit plus prononcée dans ces cas.
La différence entre le cas générique et ls -l
de 50% pourrait s'expliquer par la commande des inodes sur le disque. Si les inodes étaient disposés successivement dans le même ordre que les noms de fichiers dans le répertoire et ls -l
stat (2) ed les fichiers dans l'ordre des répertoires avant le tri, ls -l
pourrait lire la plupart des inodes dans un balayage. Avec le caractère générique, le shell triera les noms de fichiers avant de les transmettre ls
, donc ls
lira probablement les inodes dans un ordre différent, ajoutant plus de mouvement de tête de disque.
Il convient de noter que votre time
sortie n'inclura pas le temps pris par le shell pour développer le caractère générique.
Si vous voulez vraiment voir ce qui se passe, utilisez strace(1)
:
strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *
et regardez quels appels système sont effectués dans chaque cas.
¹ Je ne sais pas si elle access(2)
est réellement utilisée, ou autre chose comme stat(2)
. Mais les deux nécessitent probablement une recherche d'inode (je ne sais pas si access(file, 0)
cela contournerait une recherche d'inode).
ls
cela il suffit de demander au système de fichiers "quels sont les enfants de l'inodepwd
" où comme avecls *
il doit demander "quels sont les enfants (et quel est le fichier) de l'inodea
" suivi de b, c, d, etc. etc. Une requête contre plusieurs.