繁体   English   中英

C ++多次写入文件的有效方法

[英]C++ efficient way to write to file multiple times

我正在处理一个回调函数,根据回调中的数据,我想写入不同的文件。

例如,在一次调用中,我可能想要在使用不同数据的另一个调用中写入january.csv,它可能是july.csv。 没有预先确定的顺序,可能是每个回调中的任何一个月,我无法提前知道。 january.csv(实际所有月份)将被多次写入。

这些回调发生得非常快,所以我需要这个代码尽可能高效。

我将采取的天真方法是每次使用以下代码:

ofstream fout;
fout.open(month_string);
fout<<data_string<<endl;
fout.close();

问题是,由于我不断打开/关闭month.csv文件,这似乎不是很有效。 有没有更快的方法,我可以说保持january.csv,february.csv等一直打开,使这更快?

编辑:我在linux上写/ dev / shm所以I / O延迟不是真正的问题。

您希望减少I / O调用的数量,同时在调用它们时充分利用它们。

例如,缓存数据并将更大的块写入文件。 您可以使用另一个负责定期将缓冲区刷新到该文件的线程。

低效率的基础是双重的:等待硬盘初始化(加快速度),第二个是定位文件和写入的空扇区。无论你写的数据量多少,都会出现这种开销。 。 数据块越大,有效写入的时间就越多(盘片旋转时)。 对于Flash / Thumb驱动器也是如此; 拇指驱动器有开销(解锁,擦除等)。 因此,目标是通过写入大块来减少开销。

您可能需要考虑使用数据库: 评估对数据库的需求。

我怀疑大多数系统会允许你同时打开~10K文件,这或多或少会排除打开所有文件并根据需要写入它们。

因此,您可能只需要创建某种proxy-ish对象来缓冲每个文件的数据,当缓冲区超过某个给定大小时,打开文件,将数据写入磁盘,然后再次关闭它。

我可以看到两个相当简单的方法。 一种是使用stringstream作为缓冲区自己编写大部分代码。 客户端流向您的对象,该对象只是传递给stringstream。 然后检查字符串流是否超过某个长度,如果是,则将内容写入磁盘并清空字符串流。

另一种方法是编写自己的文件缓冲区对象,实现sync以打开文件,写入数据,然后再次关闭文件(通常会使文件始终保持打开状态)。

然后你将它们存储在std::map (或std::unordered_map )中,让你从文件名到匹配的代理对象进行查找。

我不认为一遍又一遍地打开和关闭同一个文件会是那么昂贵。 操作系统通常设计为通过在内存中缓存部分FS元数据来处理该用例。 成本主要是系统调用的上下文切换。 另一方面,在10k文件上执行此操作可能会耗尽操作系统缓存功能。

您可以通过在单个文件中依次编写带有目标的所有输出来编写日志,从而卸载一些FS工作。 然后另一个程序(FS补充程序)将执行打开该日志的任务,缓冲写入命令(按文件对它们进行分组),然后在缓冲区达到某个阈值时将它们刷新到磁盘。 您必须将日志中执行的命令标记为已提交,以便在补充剂中断并且必须恢复的情况下,它将知道还有什么要做。


更新:

可以调整文件系统,支持在同一时间打开和10000个文件高速缓存,并把它处理的调度命令的问题(这是什么FS是为制造 )。

您的问题是为您的用例选择正确的文件系统。 我建议用不同的FS进行测试,看哪哪个效果最好。

唯一剩下的部分是让程序使用std::map将文件名与其描述符相关联(平凡)。

请参阅SO以调整linux max打开文件 ,或者如果您在特定FS上找不到该文件 ,可能会询问有关该主题的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM