C ++读取大量文件的一小部分

时间:2020-09-20 18:23:47

标签: c++ c linux performance file

我有一个相对简单的问题要问,关于许多编程语言的讨论正在进行中,有关哪种方法提供最快的文件读取速度。大多是在read()mmap()上进行过辩论。作为也参加这些辩论的人,我未能找到当前问题的答案,因为大多数答案在读取文件很大的情况下很有帮助(例如,如何读取10 TB文本文件...)

但是我的问题有点不同,我有很多文件,可以说是1亿个。我想从这些文件中读取前1-2行。文件是10 kb还是100 TB无关紧要。我只想要每个文件的前一两行。因此,我想避免读取或缓冲文件中不必要的部分。我的知识不足以彻底测试哪种方法更快,或者一开始就发现我所有的选择。

我正在做的事情是正确的:(我现在正在使用多线程)

for(const auto& p: std::filesystem::recursive_directory_iterator(path)) {
    if (!std::filesystem::is_directory(p)) {
        std::ifstream   read_file(p.path().string());
        if (read_file.is_open()) {
            while (getline(read_file, line)) {
                    // Get two lines here.
            }
        }
    }
}

在这种情况下,C ++或Linux环境为我提供了什么?有没有更快或更有效的方法来读取数百万个文件的小部分?

谢谢您的时间。

信息:我可以访问C++20和Ubuntu 18.04

3 个答案:

答案 0 :(得分:2)

您可以通过 not 测试路径是否为目录来保存对fstat的一个基础调用,然后依靠is_open测试

#include <iostream>
#include <fstream>
#include <filesystem>
#include <string>

int main()
{
 std::string line,path=".";
 for(const auto& p: std::filesystem::recursive_directory_iterator(path)) {
 { 
        std::ifstream   read_file(p.path().string());
        if (read_file.is_open()) {
        std::cout << "opened: " << p.path().string() << '\n';
           while (getline(read_file, line)) {
                    // Get two lines here.
            }
        }
    }
}
}

至少在Windows上,此代码会跳过目录。而且,正如注释is_open中所建议的那样,由于getline也不从目录中读取任何内容,因此甚至可以跳过测试。

不是最干净的,但是如果可以节省时间,那是值得的。

答案 1 :(得分:0)

在Linux下访问文件的程序中的任何函数都会导致调用某些“系统调用”(例如read())。

某些编程语言中的所有其他可用函数(例如fread()fgets()std::filesystem ...)调用函数或方法,这些函数或方法又调用某些系统调用。

因此,您不能比直接调用系统调用更快。

我不确定100%,但是我认为在大多数情况下,组合open()read()close()将是从文件开头读取数据的最快方法。文件。

(如果数据不在文件开头,则pread()可能比read()快;我不确定。)

请注意,read()不会读取特定数量的行,而是读取特定数量的字节(例如,读取到char的数组中),因此您必须找到该行的末尾通过搜索'\n'数组中的char个字符和/或文件末尾来“手动”。

不幸的是,一行可能比您预期的长得多,因此从文件中读取前 N 个字节不包含前 M 行,您必须调用再次read()

在这种情况下,这取决于您的系统(例如文件系统,甚至是硬盘),在每次调用read()时应读取多少字节才能获得最佳性能。

示例:假设在所有文件的75%中,前N行位于文件的前512个字节中;在所有其他文件的25%中,前N行的总和大于512个字节。

在某些计算机上,一次读取1024个字节可能需要与读取512个字节几乎相同的时间,但是两次读取512个字节比一次读取1024个字节要慢得多。在此类计算机上,一次read() 1024字节是有意义的:您为25%的文件节省了很多时间,而为其他75%的文件只浪费了很少的时间。

在其他计算机上,读取512字节比读取1024字节要快得多。在此类计算机上,最好read() 512字节:读取1024字节将在处理25%的文件时仅节省很少的时间,而在处理其他75%的文件时则花费了很多时间。

我认为在大多数情况下,“最佳值”将是512字节的倍数,因为大多数现代文件系统都以512字节的倍数为单位组织文件。

答案 2 :(得分:0)

我只是输入类似于Martin Rosenau的答案(当他弹出时):非结构化读取两行的最大长度。但我走得更远:将具有相应文件名的文本缓冲区放入队列,然后让另一个线程解析/分析该文件。如果解析与读取大致相同的时间,则可以节省一半的时间。如果花费的时间更长(不太可能),则可以使用多个线程并节省更多线程。

旁注-您不应并行阅读(尝试这样做)。

可能值得尝试:您可以打开一个文件,在继续打开下一个文件的同时异步读取它吗?我不知道是否有任何操作系统可以重叠这些东西。

相关问题