0

我有一个由一些数据包统计信息组成的字符串,例如数据包长度等。

我想将其存储到 csv 文件中,但如果我使用标准 fprintf 写入文件,它的写入速度非常慢,我最终会丢失信息。

如何尽快将信息写入文件,以尽量减少数据包中的信息丢失。理想情况下,我希望每秒支持数百万个数据包,这意味着我需要每秒写入数百万行。

我正在使用 XDP 获取数据包信息并通过 eBPF 映射将其发送到用户空间,如果这很重要的话。

4

2 回答 2

3

最佳性能取决于硬盘驱动器、驱动器碎片、文件系统、操作系统和处理器。但是,通过写入与文件系统的磁盘结构不匹配的小块数据,永远无法实现最佳性能。

一个简单的解决方案是使用内存映射文件并让操作系统异步处理实际将数据提交到文件 - 这样它可能是您正在运行的系统的最佳选择,而您不必处理所有可能的变量或计算出系统的最佳写入块大小。

即使使用常规流 I/O,您也可以通过写入 RAM 缓冲区来显着提高性能。将缓冲区大小设置为文件系统块大小的倍数可能是最佳选择。但是,如果文件系统本身没有足够的缓冲用于排队写入或回写,则文件写入可能会阻塞,如果数据生成和数据写入发生在单个线程中,您可能不希望缓冲区太大。

另一种解决方案是有一个单独的写入线程,通过管道或队列连接到生成数据的线程。然后编写器线程可以简单地缓冲来自管道/队列的数据,直到它有一个“块”(再次匹配文件系统块大小是一个好主意),然后将该块提交给文件。然后,管道/队列充当缓冲区,存储在线程停止写入文件时生成的数据。管道、块、文件系统和磁盘写入缓存提供的缓冲可能会适应任何磁盘延迟,只要驱动器的基本写入性能比生成写入数据的速度更快 - 没有但是更快的驱动器将解决该问题。

于 2020-01-14T19:52:43.550 回答
1

用于sprintf写入内存中的缓冲区。
使该缓冲区尽可能大,当它变满时,然后使用单个fwrite将整个缓冲区转储到磁盘。希望到那时它将包含数百或数千行 CSV 数据,当您开始用更多sprintf.

于 2020-01-14T19:43:35.433 回答