我遇到以下問題。一堆數據分成10k個小文件(每個大約8-16kib)。根據用戶輸入,我必須儘可能快地加載並處理它們。更確切地說,每個數據包可以分成100-100k個文件,並且大約有1k個數據包。雖然他們大多數是較小的。從單個文件並行讀取
現在,我正在使用一個線程池,並在每個文件訪問上,下一個空閒線程打開文件,讀取它並返回準備顯示的數據。隨着未來文件數量的增長,我對這種方法並不感到滿意,特別是如果它最終可能有大約100k或更多的文件(部署這肯定會很有趣)。
所以,這個想法是將所有這些小文件合併成一個大數據包,並從中讀取。我可以保證它將是隻讀的,但是我不知道預先併發訪問一個文件的線程數(我知道最大數目)。這會給我大約1000個大小適中的文件,並且我可以輕鬆添加新的數據包。
問題是:在這種情況下,如何讓1..N個線程從單個文件中有效讀取?我可以在Windows上使用異步I/O,但對於小於64k的讀取,它應該是同步的。內存映射文件不是一種選擇,因爲預期的大小大於1.6吉比特,我仍然需要能夠在x86上運行(除非我能夠有效地映射一些小部分,讀取它,再次取消映射 - 我的經驗內存映射是它比一次讀取帶來了相當多的開銷)。
我想過打開每個數據包N次,並給每個線程一個循環方式的句柄,但問題是,它可以以(數據文件數)x(最大數量線程)打開句柄(可以很容易地變成8-16k),並且我必須在每次訪問數據包時使用同步,或者使用一些無鎖魔術來獲得下一個空閒文件句柄。因爲這似乎不是一個原始問題(我猜,任何數據庫引擎都有類似的問題,在這裏你可以有N行(文件在我的情況下)的M個表(數據包),並且你想要允許儘可能多的線程同時讀取行)。那麼這裏推薦的做法是什麼?順便說一下,它應該在Windows和Linux上運行,所以歡迎使用可移植的方法(或者至少可以在兩種平臺上工作的方法,即使它們使用不同的底層API--只要它們可以被包裝,我很高興)。
[編輯]這不是關於速度,這是關於隱藏延遲。也就是說,我可能每秒鐘讀取100個這樣的小文件,所以我最多隻能達到1 mib/s。我主要關心的是尋找時間(因爲我的訪問模式不可預測),並且我想隱藏它們,通過在向用戶顯示舊數據的同時開始讀取。問題是如何讓幾個線程通過幾個文件發出IO請求,可能有> 1個線程訪問單個文件。
如果其中一個調用需要70 ms左右才能完成,那真的沒有問題,但如果讀取調用阻塞,我無法負擔得起。
您的數據是否存儲在RAID陣列或類似的東西上? – Egwor 2009-05-03 09:58:31
不,完全沒有。同樣,速度不是主要問題,只要它是異步運行的,即使每次讀取都需要100 ms,我也可以。問題是如何讓多個線程同時訪問一個文件:) – Anteru 2009-05-03 10:01:46
我看到映射整個文件集的內存不是一個選項,但也許你可以使用一塊內存作爲訪問文件的大緩存大多數時候(或者它們全部只能被讀取一次?) – schnaader 2009-05-03 10:02:25