我有一个运行linux的目标板,目录中大约有500万多个文件。 (此目录没有任何子目录)如果我执行此程序,则需要几分钟来获取总空间信息。有没有更快的方法可以做到这一点?谢谢
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
#include <errno.h>
void calcSpace(char *path, long long int *totalSpace)
{
DIR *dir; /* dir structure we are reading */
struct dirent *ent; /* directory entry currently being processed */
char absPath[200];
struct stat statbuf; /* buffer for stat()*/
long long int fileCount=0;
fprintf(stderr, "Opening dir %s\n", path);
dir = opendir(path);
if(NULL == dir) {
perror(path);
return;
}
while((ent = readdir(dir)))
{
fileCount++;
sprintf(absPath, "%s/%s", path, ent->d_name);
if(stat(absPath, &statbuf)) {
perror(absPath);
return;
}
*totalSpace= (*totalSpace) + statbuf.st_size;
}
fprintf(stderr, "Closing dir %s\n", path);
printf("fileCount=%lld.\n", fileCount);
closedir(dir);
}
int main(int argc, char *argv[])
{
char *dir;
long long int totalSpace=0;
if(argc > 1)
dir = argv[1];
else
dir = ".";
calcSpace(dir, &totalSpace);
printf("totalSpace=%lld\n", totalSpace);
return 0;
}
如评论中所述,主要成本似乎是对stat
和readdir
的呼吁。
优化readdir
个通话
我们可以使用readdir
系统调用来节省getdents(2)
成本上的大量费用。该系统调用类似于'readdir',但是您可以使用它来读取每个系统调用中的多个目录条目-大大减少了为每个条目调用getdents(2)
系统调用的开销。
一个代码示例可以在我链接到的readdir
页面上找到。需要注意的重要事项是,您可能应该使用man
(getdents
参数-在示例中为1024)来一次读取条目的数量,以查找配置和机器的最佳位置。 (此步骤可能会为您带来比count
更高的性能提升)。
优化readdir
个通话
建议使用stat
功能,而不要使用常规的fstatat(2)
(两者都为stat
)。这是因为relevant man page的第一个参数是fstatat(2)
-您要声明的文件所在目录的文件描述符。
这意味着您可以一次使用目录dirfd
打开目录的文件描述符,然后所有的open(2)
调用都将使用此fstatat
完成。这将优化内核中的声明过程(因为不再应该为每个dirfd
syscall解析整个路径的引用和目录本身),并且可能使您的代码更简单,更快一些(作为路径)不再需要串联)。
虽然从技术上讲这不是一个“答案”,但此处对此问题有一些评论:
在幕后,大多数Linux文件系统将文件表示为'inodes',目录表示名称列表-> inode。根据文件系统的不同,列表可以是简单的线性列表,平衡树或哈希表-可以提高查找性能,并可以处理包含大量文件的文件夹。
较旧的操作系统(Vax VMS,其前身是FILES-11)必须具有通过唯一ID(文件编号,序列号)打开文件的能力,而且不能按文件路径打开文件。在Linux空间中,这等效于按inode编号打开文件。这种方法使得以很少的开销打开或查询元数据成为可能。不幸的是,Unix / Linux在应用程序级别上没有类似的功能,据我所知,还没有计划创建这样的接口。这将需要对所有文件系统驱动程序进行重大升级。
另一种方法将是实现多文件stat
系统调用,这将受益于能够在单次扫描期间对所有文件执行文件查找。虽然系统调用的类型将加快各种实用程序的速度,但它不会使大多数应用程序受益,因为大多数应用程序通常会坚持使用POSIX调用。如果不更改各种文件系统驱动程序,将很难实现这种功能。我相信它不太可能很快上市。