ls
จริง ๆ แล้วเรียงลำดับไฟล์และพยายามที่จะแสดงรายการพวกเขาซึ่งจะกลายเป็นค่าใช้จ่ายมากถ้าเราพยายามที่จะแสดงรายการมากกว่าหนึ่งล้านไฟล์ในไดเรกทอรี ตามที่กล่าวไว้ในลิงค์นี้เราสามารถใช้strace
หรือfind
เพื่อแสดงรายการไฟล์ อย่างไรก็ตามตัวเลือกเหล่านี้ดูเหมือนจะไม่สามารถแก้ปัญหาของฉันได้เนื่องจากฉันมีไฟล์ 5 ล้านไฟล์ หลังจากบิตของบาง googling ผมพบว่าถ้าเรารายการไดเรกทอรีที่ใช้getdents()
ก็ควรจะเป็นได้เร็วขึ้นเพราะls
, find
และPython
ห้องสมุดใช้readdir()
ซึ่งจะช้า แต่ใช้getdents()
ภายใต้
เราสามารถค้นหารหัส C เพื่อแสดงรายการไฟล์ที่ใช้getdents()
จากที่นี่ :
/*
* 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);
}
คัดลอกโปรแกรม C ด้านบนลงในไดเรกทอรีซึ่งต้องการแสดงไฟล์ จากนั้นดำเนินการคำสั่งด้านล่าง
gcc getdents.c -o getdents
./getdents
ตัวอย่างการกำหนดเวลา : getdents
สามารถเร็วกว่ามากขึ้นls -f
อยู่กับการกำหนดค่าระบบ นี่คือบางส่วนของเวลาที่แสดงให้เห็นถึงการเพิ่มความเร็ว 40x สำหรับการแสดงรายการไดเรกทอรีที่มีไฟล์ประมาณ 500k ผ่านเมาต์ NFS ในคลัสเตอร์การคำนวณ แต่ละคำสั่งก็วิ่ง 10 ครั้งในการทดแทนทันทีครั้งแรกแล้วgetdents
ls -f
การรันครั้งแรกช้ากว่าผู้อื่นอย่างมากอาจเป็นเพราะการแคชหน้า NFS ผิดพลาด (นอกเหนือจาก: บนเมานต์d_type
นี้ฟิลด์ไม่น่าเชื่อถือในแง่ที่ว่าไฟล์จำนวนมากปรากฏเป็นประเภท "ไม่รู้จัก")
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
ใช้งานนั้น--color
หรือ-F
หมายความว่าทำlstat(2)
สำหรับแต่ละไฟล์