我有一个相对简单的问题要问,关于许多编程语言的讨论正在进行中,有关哪种方法提供最快的文件读取速度。大多是在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
答案 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的答案(当他弹出时):非结构化读取两行的最大长度。但我走得更远:将具有相应文件名的文本缓冲区放入队列,然后让另一个线程解析/分析该文件。如果解析与读取大致相同的时间,则可以节省一半的时间。如果花费的时间更长(不太可能),则可以使用多个线程并节省更多线程。
旁注-您不应并行阅读(尝试这样做)。
可能值得尝试:您可以打开一个文件,在继续打开下一个文件的同时异步读取它吗?我不知道是否有任何操作系统可以重叠这些东西。