如果需要15US讀/準備記錄那麼你的最大吞吐量將約1秒/ 15uSec = 67K /秒。您可以忽略6uSec部分,因爲讀取文件的單個線程無法生成更多的記錄。 (嘗試它,改變程序只讀/處理和放棄輸出)不知道如何得到9uS。
爲了使這個飛過了67K /秒......
A)估計每秒可以從磁盤讀取要格式化的最高記錄。雖然這取決於硬件,但平均每檯筆記本電腦的典型值爲20Mb/s。這個數字會給你的目標上限,當你接近你可以放鬆嘗試。 B)創建一個單線程來讀取文件併產生IO延遲。這個線程應該寫入大的預分配緩衝區,比如每個4Mb。有關管理這些的方法,請參見http://en.wikipedia.org/wiki/Circular_buffer。 (!猜測,但不只是8 ISH記錄)您正在尋找持有也許1000個記錄每個緩衝區僞代碼:
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帶寬作爲限制因素。
來源
2013-03-03 18:43:34
rlb
太棒了!這很棒。你的代碼是否是開源的?如果是這樣,你能指出我嗎? – KodeWarrior 2013-03-04 20:15:16
關於B)和C)的問題 您是說我們讀取4mb數據塊並將其存儲在預先分配的緩衝區中,然後讀取緩衝區以將數據轉換爲記錄,並使用另一個線程實際發送記錄? – KodeWarrior 2013-03-04 23:20:46
用僞代碼更新了回覆,通過iPad很難做到。代碼不是開源的,但可能只能刪除關鍵部分,將檢查和建議。它是Windows C++,儘管很容易看到unix等價物(也許我需要刪除重疊的IO部分,它爲磁盤讀取發出多個異步IO,這是特定於Windows的) – rlb 2013-03-05 02:59:13