lsthực sự sắp xếp các tệp và cố gắng liệt kê chúng trở thành một chi phí khổng lồ nếu chúng ta đang cố gắng liệt kê hơn một triệu tệp trong một thư mục. Như đã đề cập trong liên kết này , chúng tôi có thể sử dụng stracehoặc findliệt kê các tệp. Tuy nhiên, những tùy chọn đó cũng có vẻ không khả thi đối với vấn đề của tôi vì tôi có 5 triệu tệp. Sau một chút loay hoay, tôi thấy rằng nếu chúng tôi liệt kê các thư mục sử dụng getdents(), nó được cho là nhanh hơn, bởi vì ls, findvà Pythoncác thư viện sử dụng readdir()chậm hơn nhưng sử dụng getdents()bên dưới.
Chúng tôi có thể tìm mã C để liệt kê các tệp bằng cách sử dụng getdents()từ đây :
/*
* 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);
}
Sao chép chương trình C ở trên vào thư mục chứa các tệp cần được liệt kê. Sau đó thực hiện các lệnh dưới đây.
gcc getdents.c -o getdents
./getdents
Ví dụ về thời gian : getdentscó thể nhanh hơn nhiều ls -f, tùy thuộc vào cấu hình hệ thống. Dưới đây là một số thời gian biểu thị tốc độ tăng 40 lần để liệt kê một thư mục chứa khoảng 500k tệp trên giá trị NFS trong cụm tính toán. Mỗi lệnh được chạy 10 lần liên tiếp, đầu tiên getdents, sau đó ls -f. Lần chạy đầu tiên chậm hơn đáng kể so với tất cả những lần khác, có thể là do lỗi trang bộ nhớ đệm NFS. (Ngoài ra: trên giá trị này, d_typetrường không đáng tin cậy, theo nghĩa là nhiều tệp xuất hiện dưới dạng "không xác định".)
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%
lsviệc sử dụng--colorhoặc-Fđiều đó có nghĩa là thực hiện mộtlstat(2)cho mỗi tệp.