我有一些长循环,我需要在每次迭代时将一些数据写入文件。问题是写入文件可能很慢,所以我希望通过异步写入来减少这个时间。
有谁知道这样做的好方法?我应该创建一个线程,通过写出来消耗放入缓冲区的任何东西(在这种情况下,单个生产者,单个消费者)?
我最感兴趣的是除了标准库(C ++ 11)之外什么都不涉及的解决方案。
答案 0 :(得分:14)
在进入异步写入之前,如果您正在使用IOStream,您可能希望尝试避免意外刷新流,例如,使用std::endl
而不是,而是使用{{1}而是。由于写入IOStreams是缓冲的,因此可以提高性能。
如果这还不够,下一个问题是如何写入数据。如果正在进行大量格式化,则实际格式化有可能占用大部分时间。您可能能够将格式化推送到单独的线程中,但这与仅仅将几个字节写入另一个线程完全不同:您需要传递一个合适的数据结构来保存要格式化的数据。什么是合适的取决于你实际写的是什么。
最后,如果将缓冲区写入文件确实是瓶颈并且您希望坚持使用标准C ++库,那么让编写器线程侦听充满缓冲区的队列并从合适的流缓冲区中进行操作可能是合理的。将缓冲区写入'\n'
:生成器接口将是std::ofstream
,当缓冲区已满或刷新流时,它会发送可能固定大小的缓冲区(我将使用{ {1}}显式地)到另一个读取侦听的队列。以下是仅使用标准库工具的快速实现:
std::ostream
答案 1 :(得分:1)
在网络上搜索“双缓冲”。
通常,一个线程将写入一个或多个缓冲区。另一个线程从缓冲区读取“追逐”写作线程。
这可能无法提高您的计划效率。通过写入大块来实现文件的效率,以便驱动器没有机会降速。一次写入多个字节比几个字节的多次写入更有效。
这可以通过使写入线程仅在缓冲区内容超过某个阈值(如1k)时写入来实现。
还研究“假脱机”或“打印假脱机”这一主题。
您需要使用C ++ 11,因为以前的版本在标准库中没有线程支持。我不知道为什么你限制自己,因为Boost有一些好东西。