如何有效地将结构向量写入文件?
Posted
技术标签:
【中文标题】如何有效地将结构向量写入文件?【英文标题】:How to efficiently write a vector of structs to file? 【发布时间】:2013-02-02 22:51:30 【问题描述】:我的代码将大小大于 1000 万的向量写入文本文件。我使用 clock() 来计时 writefile 函数及其程序中最慢的部分。有没有比我下面的方法更好的写入文件的方法?
void writefile(vector<fields>& fieldsvec, ofstream& sigfile, ofstream& noisefile)
/* Writes clean and noise data to respective files
*
* fieldsvec: vector of clean data
* noisevec: vector of noise data
* sigfile: file to store clean data
* noisefile: file to store noise data
*/
for(unsigned int i=0; i<fieldsvec.size(); i++)
if(fieldsvec[i].nflag==false)
sigfile << fieldsvec[i].timestamp << ";" << fieldsvec[i].price << ";" << fieldsvec[i].units;
sigfile << endl;
else
noisefile << fieldsvec[i].timestamp << ";" << fieldsvec[i].price << ";" << fieldsvec[i].units;
noisefile << endl;
我的结构在哪里:
struct fields
// Stores a parsed line of a file
public:
string timestamp;
float price;
float units;
bool nflag; //flag if noise (TRUE=NOISE)
;
【问题讨论】:
你可以回退到 fread/fwrite 的旧 C i/o 函数,看看是否更快? 我打赌“fprintf()”会比ostream
快很多——不幸的是,它需要一些重写,使用“FILE *”而不是“ostream&”作为输入函数。
【参考方案1】:
我建议摆脱endl
。这样每次都有效地刷新缓冲区,从而大大增加了系统调用的数量。
写'\n'
而不是endl
应该是一个很好的改进。
顺便说一句,代码可以简化:
ofstream& files[2] = sigfile, noisefile ;
for(unsigned int i=0; i<fieldsvec.size(); i++)
files[fieldsvec[i].nflag] << fieldsvec[i].timestamp << ';' << fieldsvec[i].price << ";\n";
【讨论】:
@riotburn:我很想听听您使用未修改代码的计时结果,仅将std::endl
更改为'\n'
。另请注意,ipc 推荐 character '\n'
,而不是 "\n"
的 const char*
。请让我们知道这种变化会带来什么样的不同!
所以在进行任何更改之前,writefile 需要 107.8 秒。使用“\n”现在需要 41.8 秒!使用 '\n' 需要 40.63 秒。有什么不同! @ipc 我尝试使用您将文件存储在数组中的聪明想法,但出现以下错误:scrub.cpp:174:22: error: declaration of ‘files’ as array of reference
我的虚拟机在打开一段时间后变得缓慢,所以我重新启动它,写入文件功能需要 35 秒。所以结果可能有点偏差,但它的对接加载速度更快。现在它是我最快的功能,所以我要努力加快读取和过滤功能。【参考方案2】:
您可以按照the first answer of this SO question 中的建议以二进制格式而不是文本格式编写文件以提高写入速度:
file.open(filename.c_str(), ios_base::binary);
...
// The following writes a vector into a file in binary format
vector<double> v;
const char* pointer = reinterpret_cast<const char*>(&v[0]);
size_t bytes = v.size() * sizeof(v[0]);
file.write(pointer, bytes);
从同一链接,OP 报告:
将 std::endl 替换为 \n 将代码速度提高了 1% 将所有要写入的内容串联在一个流中,最后将所有内容写入文件中,代码速度提高了 7% 将文本格式更改为二进制格式使他的代码速度提高了 90%。【讨论】:
@riotburn:正如 Etienne 所建议的那样,您也非常想知道使用二进制 I/O 而非文本可以获得什么样的性能提升!请告诉我们! 这是一个很好的建议,但不幸的是我必须将其保留为文本格式。谢谢!【参考方案3】:一个重要的速度杀手是您将数字转换为文本。
至于原始文件输出,ofstream
上的缓冲默认情况下应该非常有效。
您应该将数组作为 const 引用传递。这可能没什么大不了,但它确实允许某些编译器优化。
如果您认为流因为重复写入而搞砸了,您可以尝试使用sprintf
或snprintf
创建一个字符串并写入一次。仅当您的时间戳是已知大小时才执行此操作。当然,这会产生额外的复制,因为必须将字符串放入输出缓冲区。实验。
否则,它会开始变脏。当您需要调整文件的性能时,您需要开始为您的应用程序定制缓冲区。这往往归结为不使用缓冲或缓存、对自己的缓冲区进行扇区对齐以及写入大块。
【讨论】:
以上是关于如何有效地将结构向量写入文件?的主要内容,如果未能解决你的问题,请参考以下文章