ls
sebenarnya mengurutkan file dan mencoba untuk membuat daftar yang menjadi overhead besar jika kita mencoba mendaftar lebih dari satu juta file di dalam direktori. Seperti disebutkan dalam tautan ini , kita dapat menggunakan strace
atau find
untuk membuat daftar file. Namun, opsi-opsi itu juga tampak tidak mungkin untuk masalah saya karena saya memiliki 5 juta file. Setelah sedikit googling, saya menemukan bahwa jika kita daftar direktori menggunakan getdents()
, itu seharusnya lebih cepat, karena ls
, find
dan Python
perpustakaan menggunakan readdir()
yang lebih lambat tetapi menggunakan di getdents()
bawahnya.
Kita dapat menemukan kode C untuk membuat daftar file yang digunakan getdents()
dari sini :
/*
* 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);
}
Salin program C di atas ke dalam direktori di mana file harus terdaftar. Kemudian jalankan perintah di bawah ini.
gcc getdents.c -o getdents
./getdents
Contoh waktu : getdents
bisa lebih cepat daripada ls -f
, tergantung pada konfigurasi sistem. Berikut adalah beberapa pengaturan waktu yang menunjukkan peningkatan kecepatan 40x untuk daftar direktori yang berisi sekitar 500k file di atas mount NFS di cluster komputasi. Setiap perintah dijalankan 10 kali berturut-turut, pertama getdents
, lalu ls -f
. Jalankan pertama secara signifikan lebih lambat dari yang lain, mungkin karena kesalahan halaman caching NFS. (Selain: di atas mount ini, d_type
bidang ini tidak dapat diandalkan, dalam arti bahwa banyak file muncul sebagai tipe "tidak dikenal".)
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
penggunaan itu--color
atau-F
karena artinya melakukanlstat(2)
untuk setiap file.