在Linux中以更快的方式获取包含500万个文件的目录所占用的总空间

m4n*_*n07 5 c c++ linux embedded-linux

我有一个运行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;
}
Run Code Online (Sandbox Code Playgroud)

小智 1

正如评论中所述,主要成本似乎是stat和 的调用readdir

优化readdir通话

readdir我们可以使用系统调用来节省一些严重的成本getdents(2)。此系统调用类似于“readdir”,但您可以使用它来读取每个系统调用中的多个目录条目 - 大大减少了调用的开销readdir为每个条目调用系统调用的开销。

man可以在我链接到的页面中找到代码示例。getdents需要注意的重要一点是,您可能应该使用(参数 - 在示例中为 1024)调整一次读取的条目数量count,以找到您的配置和机器的最佳位置(此步骤可能会给出您想要的性能改进readdir)。

优化stat通话

建议使用该fstatat(2)函数而不是stat您使用的常规函数​​(两者的相关手册页)。这是因为第一个参数fstatat(2)dirfd- 您所声明的文件所在目录的文件描述符。

这意味着您可以打开目录的文件描述符一次(使用open(2)),然后所有fstatat调用都将使用此完成dirfd。这将优化内核中的声明过程(因为不应再为每个系统调用解析整个路径和目录本身的引用stat),并且可能会使您的代码更简单且更快一点(因为路径串联不会不再需要)。