如果读取/准备一条记录需要 15uS,那么您的最大吞吐量将约为 1sec/15uSec = 67k/sec。您可以忽略 6uSec 部分,因为读取文件的单个线程无法生成更多记录。(尝试一下,将程序更改为仅读取/处理并丢弃输出)不确定您是如何获得 9uS 的。
为了让这个速度超过 67k/sec ...
A) 估计每秒可以从要格式化的磁盘读取的最大记录数。虽然这在很大程度上取决于硬件,但对于普通笔记本电脑来说,20Mb/sec 的数字是典型的。这个数字将为您提供目标的上限,当您接近时,您可以轻松尝试。
B)创建一个线程只是为了读取文件并导致IO延迟。该线程应该写入大的预分配缓冲区,例如每个 4Mb。有关管理这些内容的方法,请参见http://en.wikipedia.org/wiki/Circular_buffer。您希望每个缓冲区保存 1000 条记录(猜测,但不仅仅是 8 条记录!)伪代码:
while not EOF
Allocate big buffer
While not EOF and not buffer full
Read file using fgets() or whatever
Apply only very small preprocessing, ideally none
Save into buffer
Release buffer for other threads
C)创建另一个线程(或多个,如果记录的顺序不重要)来处理一个满的环形缓冲区,你的正则表达式步骤。该线程依次写入另一组输出环形缓冲区(提示,保持环形缓冲区控制结构在内存中分开)
While run-program
Wait/get an input buffer to process, semaphores/mutex/whatever you prefer
Allocate output buffer
Process records from input buffer,
Place result in output buffer
Release output buffer for next thread
Release input buffer for reading thread
D)创建最终线程来使用数据。目前尚不清楚此输出是否正在写入磁盘或网络,因此这可能会影响磁盘读取线程。
Wait/get input buffer from processed records pool
Output records to wherever
Return buffer to processed records pool
笔记。预分配所有缓冲区并将它们传递回它们的来源。例如,您可能在文件读取线程和处理线程之间有 4 个缓冲区,当所有 4 个都注入时,文件读取器等待一个空闲,它不只是分配新的缓冲区。如果可以避免,尽量不要使用 memset() 缓冲区,浪费内存带宽。你不需要很多缓冲区,6?每个环形缓冲区?
系统将自动调整到最慢的线程(http://en.wikipedia.org/wiki/Theory_of_constraints),因此如果您读取和准备数据的速度比您想要输出的速度快,所有缓冲区都会填满,一切都会暂停,除了输出。
由于线程在每个同步点传递合理数量的数据,因此开销不会太大。
上面的设计是我的一些代码如何尽可能快地读取 CSV 文件,基本上都是将输入 IO 带宽作为限制因素。