将数据连续写入文件的 C 最快方法 [关闭]
Posted
技术标签:
【中文标题】将数据连续写入文件的 C 最快方法 [关闭]【英文标题】:C fastest way to continously write data to file [closed] 【发布时间】:2020-05-01 14:01:58 【问题描述】:我有一个由一些数据包统计信息组成的字符串,例如数据包长度等。
我想将其存储到 csv 文件中,但如果我使用标准 fprintf 写入文件,它的写入速度非常慢,最终会丢失信息。
如何尽快将信息写入文件,以尽量减少数据包中的信息丢失。理想情况下,我希望每秒支持数百万个数据包,这意味着我需要每秒写入数百万行。
如果这很重要,我正在使用 XDP 获取数据包信息并通过 eBPF 映射将其发送到用户空间。
【问题讨论】:
你能把更大的块写入文件吗?而不是写一个单一的值写 100s 或 1000s?也许使用双缓冲区:将新值写入一个缓冲区,同时将另一个缓冲区的内容写入文件。 你是否在两次连续写入之间关闭流? "...每秒数百万个数据包..." 没有告诉我们任何信息,因为这些是未公开长度的字符串。这些字符串有多长?还有什么是突发长度 - 这些数据是无限期地流过还是可以在“安静”期间被缓冲和提交。 (你知道没有你的代码很难提供帮助吗?)fprintf
不是你的瓶颈。文件 I/O 可能是。如果您正在向其写入日志的设备无法跟上传入的数据包,那么任何软件修复都无济于事。也许您想要登录到 SSD,甚至创建一个 ram 磁盘?
【参考方案1】:
最佳性能取决于硬盘驱动器、驱动器碎片、文件系统、操作系统和处理器。但是,写入与文件系统的磁盘结构不匹配的小块数据永远无法实现最佳性能。
一个简单的解决方案是使用 内存映射文件 并让操作系统异步处理实际将数据提交到文件 - 这样可能最适合您正在运行的系统无需处理所有可能的变量或计算出系统的最佳写入块大小。
即使使用常规流 I/O,您也可以通过写入 RAM 缓冲区来显着提高性能。将缓冲区大小设置为文件系统块大小的倍数可能是最佳选择。但是,如果文件系统本身没有足够的缓冲用于排队写入或回写,则文件写入可能会阻塞,因此如果数据生成和数据写入发生在单个线程中,您可能不希望缓冲区太大。
另一种解决方案是有一个单独的写入线程,通过管道或队列连接到生成数据的线程。然后编写器线程可以简单地缓冲来自管道/队列的数据,直到它有一个“块”(再次匹配文件系统块大小是一个好主意),然后将该块提交给文件。然后,管道/队列充当缓冲区,存储在线程停止写入文件时生成的数据。管道、块、文件系统和磁盘写入缓存提供的缓冲可能会适应任何磁盘延迟,只要驱动器的基本写入性能比生成写入数据的速度更快 - 没有但更快的驱动器会解决这个问题。
【讨论】:
【参考方案2】:使用sprintf
写入内存中的缓冲区。
使该缓冲区尽可能大,当它已满时,然后使用单个fwrite
将整个缓冲区转储到磁盘。希望到那时它会包含成百上千行 CSV 数据,当您开始用更多 sprintf
填充另一个内存缓冲区时,这些数据将立即写入。
【讨论】:
以上是关于将数据连续写入文件的 C 最快方法 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ 中同时写入文件(换句话说,写入文件的最快方法是啥)
Python:在多张工作表上将 Pandas DataFrame 写入 Excel 的最快方法