lsfaktycznie sortuje pliki i próbuje je wyświetlić, co staje się ogromnym narzutem, jeśli próbujemy wyświetlić ponad milion plików w katalogu. Jak wspomniano w tym linku, możemy użyć stracelub findwyświetlić listę plików. Jednak te opcje również wydawały się niewykonalne dla mojego problemu, ponieważ miałem 5 milionów plików. Po trochę googlingu, odkryłem, że jeśli wymienimy listę używanych katalogów getdents(), powinno to być szybsze, ponieważ ls, findi Pythonbiblioteki używają tego, readdir()co jest wolniejsze, ale używa getdents()pod spodem.
Możemy znaleźć kod C, aby wyświetlić listę plików przy użyciu getdents()od tutaj :
/*
* 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);
}
Skopiuj powyższy program C do katalogu, w którym pliki muszą być wymienione. Następnie wykonaj poniższe polecenia.
gcc getdents.c -o getdents
./getdents
Przykład taktowania : getdentsmoże być znacznie szybszy niż ls -f, w zależności od konfiguracji systemu. Oto niektóre czasy pokazujące 40-krotny wzrost prędkości dla umieszczenia katalogu zawierającego około 500 tys. Plików przez podłączenie NFS w klastrze obliczeniowym. Każda komenda został uruchomiony 10 razy w bezpośredniej kolejności, najpierw getdents, potem ls -f. Pierwsze uruchomienie jest znacznie wolniejsze niż wszystkie inne, prawdopodobnie z powodu błędów strony buforowania NFS. (Poza tym: w przypadku tego montażu d_typepole jest niewiarygodne, w tym sensie, że wiele plików jest wyświetlanych jako „nieznane”).
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, który używa--colorlub-Fjako oznaczałoby to robilstat(2)dla każdego pliku.