Quando você executa ls sem argumentos, ele simplesmente abre um diretório, lê todo o conteúdo, ordena-os e os imprime.
Quando você executa ls * , primeiro o shell expande * , que é efetivamente o mesmo que o simples ls , cria um vetor de argumento com todos os arquivos no diretório atual e chama ls . ls tem que processar esse vetor de argumento e para cada argumento e chama access(2) ¹ o arquivo para verificar sua existência. Em seguida, imprimirá a mesma saída que o primeiro (simples) ls . O processamento do shell do vetor de argumentos grandes e ls provavelmente envolverá muita alocação de memória de blocos pequenos, o que pode levar algum tempo. No entanto, como havia pouco sys e user time, mas muito real time, a maior parte do tempo teria sido gasta aguardando disco, em vez de usar CPU fazendo alocação de memória.
Cada chamada para access(2) precisará ler o inode do arquivo para obter as informações de permissão. Isso significa muito mais disco lê e procura do que simplesmente ler um diretório. Eu não sei o quão caras são essas operações no seu GPFS, mas como a comparação que você mostrou para ls -l , que tem um tempo de execução semelhante ao caso curinga, o tempo necessário para recuperar as informações do inode parece dominar. Se o GPFS tiver uma latência ligeiramente maior que o sistema de arquivos local em cada operação de leitura, esperaríamos que ele fosse mais pronunciado nesses casos.
A diferença entre o caso curinga e ls -l de 50% pode ser explicada pela ordenação de inodes no disco. Se os inodes foram dispostos sucessivamente na mesma ordem em que os nomes de arquivos no diretório e ls -l stat (2) editaram os arquivos na ordem de diretórios antes de classificar, ls -l possivelmente leria a maioria dos inodes em uma varredura. Com o caractere curinga, o shell classificará os nomes dos arquivos antes de passá-los para ls , portanto, ls provavelmente lerá os inodes em uma ordem diferente, adicionando mais movimento da cabeça do disco.
Deve-se observar que sua saída time não incluirá o tempo gasto pelo shell para expandir o curinga.
Se você realmente quiser ver o que está acontecendo, use strace(1) :
strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *
e veja quais chamadas do sistema estão sendo executadas em cada caso.
¹ Eu não sei se access(2) é realmente usado, ou algo mais como stat(2) . Mas ambos provavelmente requerem uma pesquisa de inode (não tenho certeza se access(file, 0) iria ignorar uma pesquisa de inode).