ls
na verdade classifica os arquivos e tenta listá-los, o que se torna uma enorme sobrecarga se estivermos tentando listar mais de um milhão de arquivos dentro de um diretório. Conforme mencionado neste link, podemos usar strace
ou find
para listar os arquivos. No entanto, essas opções também pareciam inviáveis para o meu problema, pois eu tinha 5 milhões de arquivos. Depois de algum pouco de googling, eu achei que, se listar os diretórios usando getdents()
, que é suposto ser mais rápido, porque ls
, find
e Python
bibliotecas de usar readdir()
que é mais lento, mas usa getdents()
por baixo.
Podemos encontrar o código C para listar os arquivos usando getdents()
a partir daqui :
/*
* List directories using getdents() because ls, find and Python libraries
* use readdir() which is slower (but uses getdents() underneath.
*
* Compile with
* ]$ gcc getdents.c -o getdents
*/
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; ) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG ) {
printf("%s\n", (char *)d->d_name );
}
bpos += d->d_reclen;
}
}
exit(EXIT_SUCCESS);
}
Copie o programa C acima no diretório em que os arquivos precisam ser listados. Em seguida, execute os comandos abaixo.
gcc getdents.c -o getdents
./getdents
Exemplo de tempos : getdents
pode ser muito mais rápido que ls -f
, dependendo da configuração do sistema. Aqui estão alguns horários que demonstram um aumento de velocidade de 40x para listar um diretório que contém cerca de 500k arquivos em uma montagem NFS em um cluster de computação. Cada comando foi executado 10 vezes em sucessão imediata, primeiro getdents
e depois ls -f
. A primeira execução é significativamente mais lenta que todas as outras, provavelmente devido a falhas na página de cache do NFS. (Além disso: nessa montagem, o d_type
campo não é confiável, no sentido de que muitos arquivos aparecem como do tipo "desconhecido".)
command: getdents $bigdir
usr:0.08 sys:0.96 wall:280.79 CPU:0%
usr:0.06 sys:0.18 wall:0.25 CPU:97%
usr:0.05 sys:0.16 wall:0.21 CPU:99%
usr:0.04 sys:0.18 wall:0.23 CPU:98%
usr:0.05 sys:0.20 wall:0.26 CPU:99%
usr:0.04 sys:0.18 wall:0.22 CPU:99%
usr:0.04 sys:0.17 wall:0.22 CPU:99%
usr:0.04 sys:0.20 wall:0.25 CPU:99%
usr:0.06 sys:0.18 wall:0.25 CPU:98%
usr:0.06 sys:0.18 wall:0.25 CPU:98%
command: /bin/ls -f $bigdir
usr:0.53 sys:8.39 wall:8.97 CPU:99%
usr:0.53 sys:7.65 wall:8.20 CPU:99%
usr:0.44 sys:7.91 wall:8.36 CPU:99%
usr:0.50 sys:8.00 wall:8.51 CPU:100%
usr:0.41 sys:7.73 wall:8.15 CPU:99%
usr:0.47 sys:8.84 wall:9.32 CPU:99%
usr:0.57 sys:9.78 wall:10.36 CPU:99%
usr:0.53 sys:10.75 wall:11.29 CPU:99%
usr:0.46 sys:8.76 wall:9.25 CPU:99%
usr:0.50 sys:8.58 wall:9.13 CPU:99%
ls
esses usos--color
ou-F
isso significaria fazer umlstat(2)
para cada arquivo.