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

问题描述 投票:5回答:2

我有一个运行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;
}
c++ c linux embedded-linux
2个回答
1
投票

如评论中所述,主要成本似乎是对statreaddir的呼吁。

优化readdir个通话

我们可以使用readdir系统调用来节省getdents(2)成本上的大量费用。该系统调用类似于'readdir',但是您可以使用它来读取每个系统调用中的多个目录条目-大大减少了为每个条目调用getdents(2)系统调用的开销。

一个代码示例可以在我链接到的readdir页面上找到。需要注意的重要事项是,您可能应该使用mangetdents参数-在示例中为1024)来一次读取条目的数量,以查找配置和机器的最佳位置。 (此步骤可能会为您带来比count更高的性能提升)。

优化readdir个通话

建议使用stat功能,而不要使用常规的fstatat(2)(两者都为stat)。这是因为relevant man page的第一个参数是fstatat(2)-您要声明的文件所在目录的文件描述符。

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


0
投票

虽然从技术上讲这不是一个“答案”,但此处对此问题有一些评论:

在幕后,大多数Linux文件系统将文件表示为'inodes',目录表示名称列表-> inode。根据文件系统的不同,列表可以是简单的线性列表,平衡树或哈希表-可以提高查找性能,并可以处理包含大量文件的文件夹。

较旧的操作系统(Vax VMS,其前身是FILES-11)必须具有通过唯一ID(文件编号,序列号)打开文件的能力,而且不能按文件路径打开文件。在Linux空间中,这等效于按inode编号打开文件。这种方法使得以很少的开销打开或查询元数据成为可能。不幸的是,Unix / Linux在应用程序级别上没有类似的功能,据我所知,还没有计划创建这样的接口。这将需要对所有文件系统驱动程序进行重大升级。

另一种方法将是实现多文件stat系统调用,这将受益于能够在单次扫描期间对所有文件执行文件查找。虽然系统调用的类型将加快各种实用程序的速度,但它不会使大多数应用程序受益,因为大多数应用程序通常会坚持使用POSIX调用。如果不更改各种文件系统驱动程序,将很难实现这种功能。我相信它不太可能很快上市。

© www.soinside.com 2019 - 2024. All rights reserved.