2013-03-14 60 views
1

我的任務是提供一個形式非常大(50GB +)ASCII文本文件隨機讀取訪問(第n行的處理請求/在第n行的第n個字)的C#控制檯應用程序。一個非常大(50GB +)ASCII文件,提供隨機讀取訪問

google搜索和閱讀了幾天後,我來執行這樣的願景: 由於的StreamReader擅長順序存取,用它來建立的文件中的行/字的索引(List<List<long>>地圖,其中map[i][j]是第i行第j個詞開始的位置)。然後使用索引通過MemoryMappedFile訪問文件,因爲它擅長提供隨機訪問。

是否有解決一些明顯的缺陷?對於給定的任務它會是最優的嗎?

UPD:它將在64位系統中執行。

+0

即使這個列表可能會相當大。我可能只是有一些索引結構,比如一棵平衡樹,每隔100行左右開始文件偏移,然後在那裏尋找並讀取一個緩衝區,然後可以解析這個緩衝區以找到你正在尋找的確切單詞。 – 2013-03-14 21:21:57

+0

我會純粹以字節爲單位創建索引(即使用Stream而不是StreamReader),但除此之外聽起來不錯。如果每行的單詞不是太多,則只需索引行並在每次請求時搜索單詞可能會更有效。儘可能延遲創建'String'對象。 – dtb 2013-03-14 21:21:59

回答

5

這似乎很好,但如果你使用MemoryMapping那麼你的程序將只能在64位系統上,因爲你excessing可用的有效2GB地址空間的工作。

只要使用FileStream並調用.Seek()來適當地跳轉到選定的偏移量就可以了,所以我沒有看到使用MemoryMapped文件的必要性。

+0

我可以看到使用MemoryMapped文件的優勢,例如,當相關數據位於附近且頁面仍在物理內存中時。我不確定如果你在Stream with Seek中跳轉,你是否會獲得同樣的優勢。 – dtb 2013-03-14 21:25:38

+0

2GB限制可以使用'MemoryMappedViewAccessor'來繞過。它就像一個進入記憶的窗口。 – 2013-03-14 21:31:10

+0

如果FilesStream.Seek()與通過MMF訪問特定位置一樣快(這是真的嗎?),那麼爲什麼我們需要MMF? – vorou 2013-03-15 05:47:45

2

我相信您的解決方案是一個良好的開端 - 即使你列表容器是不是最好的地圖容器 - 列表是讀取任意元素非常緩慢。因爲操作系統在頁面邊界(x86/x64上的4096字節)緩存內存映射,所以查找地址可能實際上更快一些每行的開始,然後掃描該行尋找單詞。

顯然,這種做法只會對64位操作系統的工作,而是一個MMAP的性能好處是顯著 - 這是少數地方去64位是相當重要的一個 - 數據庫應用程序:)

+0

「列表讀取非常慢的元素」 - 沒有得到它,列表[n]是O(1),不是嗎? – vorou 2013-03-15 05:53:12

+0

也沒有關於行/字比率的說法,整個50GB文件可能由一行代碼組成,一個單詞可能比一行代碼大得多,所以我認爲我應該將行和詞視爲平等。 – vorou 2013-03-15 05:57:20