【发布时间】:2012-12-02 20:36:59
【问题描述】:
我正在做一些项目,我想知道哪种方式最有效地从文件中读取大量数据(我说的是 100 行到大约 30 亿行的文件,可以多想想)。读取后,数据将存储在结构化数据集中(vector<entry> 其中“entry”定义了结构化行)。
此文件的结构化行可能如下所示:
string int int int string string
它也以适当的平台EOL 结尾,并以TAB 分隔
我希望完成的是:
- 将文件读入内存(
string)或vector<char> - 从我的缓冲区中读取原始数据并将其格式化到我的数据集中。
我需要考虑内存占用并具有快速的解析率。
我已经避免使用stringstream,因为它们看起来太慢了。
我还避免了对我的文件的多次 I/O 调用,方法是:
// open the stream
std::ifstream is(filename);
// determine the file length
is.seekg(0, ios_base::end);
std::size_t size = is.tellg();
is.seekg(0, std::ios_base::beg);
// "out" can be a std::string or vector<char>
out.reserve(size / sizeof (char));
out.resize(size / sizeof (char), 0);
// load the data
is.read((char *) &out[0], size);
// close the file
is.close();
我考虑过使用这个巨大的std::string,然后逐行循环,我会将行信息(字符串和整数部分)提取到我的数据集行中。有没有更好的方法来做到这一点?
编辑:此应用程序可以在 32 位、64 位计算机上运行,或者在超级计算机上运行更大的文件。
非常欢迎任何建议。
谢谢
【问题讨论】:
-
我不是这个领域的专家,但是你需要非常小心的是你的向量!如果您要存储条目而不是指针(智能),那么每次调整矢量大小时,您最终都会复制所有对象。如果您的原始文件为您提供了带有项目数的标题,请确保
reserve这些元素的向量 -
使用如此简单的格式,解析速度是无关紧要的。无论您做什么,它仍然会比从光盘中实际读取文件快一千倍(!)。由于内存消耗,一次性将文件读入内存也不是一个特别好的解决方案。但是,将输入分块会有所帮助。如果你真的需要高性能,那么内存映射文件就没有办法了。
-
所有常见的 I/O 库(如 C++ 流和 C stdio)都会为您进行缓冲。大多数操作系统会发现您正在按顺序读取一个大文件并为您提前读取。所有的调优都应该是数据驱动的。因此,编写一段干净的代码,然后对其进行概要分析,以了解时间的去向。
-
假设你的 3 个字符串是 1 个字节长,每个 int 是 4 个字节,每个条目至少需要 18 个字节。对于 30 亿行数据,您所说的内存是 54 GB。这不适合 32 位进程。对于 64 位进程,大多数台式机(具有 8 GB RAM)将开始抖动并变得非常慢。
标签: c++ performance multiplatform