2012-01-30 78 views
-1

首先,我得到了這個巨大的xml文件,它代表了設備收集的數據。我把它轉換成一個對象。實際上,這個對象有一個對象列表。這些對象有三個字符串。該字符串是這樣的:非常沉重的數據導致了foreach中的內存不足異常

0,12987; 0,45678; ...

這是某種形式的演出事宜安排這樣的雙列表。每個字符串中有1k個雙打,所以每個對象有3k個,並且有一些類似3k對象的東西,只是爲了讓您瞭解一個典型案例。

當我讀取數據時,我最常從objets中獲得所有雙打,並將它們添加到同一個列表中。我在foreach中創建了一個「包含三個雙精度的對象」(每個字符串對應一個),我得到每個對象,然後將我的字符串分解爲數組。之後,我循環將我的數組轉換爲「包含三個雙打的對象」列表,並將其全部添加到一個列表中,以便我可以將其用於進一步的操作。

它會在結束之前導致內存不足異常。想法?與linq的東西將是最好的。

我有什麼看起來是這樣的:

+5

也許你可以發佈你的代碼;) – ken2k 2012-01-30 14:34:04

+1

段落可以使它更容易閱讀。 :) – 2012-01-30 14:35:51

+1

3k * 3雙打〜250k字節,不夠OOM – 2012-01-30 14:39:17

回答

3

讓我們做一些數學。每個字符串1000個值*每個值8個字符(6位數加逗號和分號)*每個字符2個字節*每個對象3個字符串=每個對象48,000個字節。這本身並不是很多,即使有3000個對象,我們仍然只談論大約150MB的RAM。對現代系統來說,這仍然沒有什麼。轉換爲double數組甚至更少,因爲每個值只有8個字節,而不是16個。字符串也是引用類型,所以在字符串版本中也會有開銷。重要的是,不管你如何使用它,你仍然遠遠沒有達到85,000字節的閾值,因爲它們被困在大對象堆上,這是OutOfMemoryException的正常來源。

沒有代碼很難跟着你在做什麼,但我有幾個不同的猜測:

  1. 許多在你的字符串值都在5位數以上,這樣你穿越魔術畢竟85,000字節的門檻,你的對象最終在垃圾收集器中的大對象堆。因此,它們不會被收集,並且隨着您繼續處理對象,您很快就會將自己從地址空間(而不是真實的RAM)中移出。
  2. 你正在提取你的雙打,你反覆重建字符串的方式。這會在垃圾回收器上產生很多內存壓力,因爲它會一遍又一遍地重新創建字符串。
  3. 如果這是一個長時間運行的程序,其中每個字符串中的項目大小和數量可能會有很大差異,那麼隨着時間的推移,您可能會遇到一些大型值列表, 85,000字節的標記。

無論哪種方式,你想要在這裏做的是停止列表方面的事情,並開始思考序列。請嘗試IEnumerable<string>IEnumerable<double>,而不是List<string>List<double>。爲您的字符串編寫一個解析器,該解析器使用yield關鍵字創建一個迭代器塊,通過迭代字符而不更改字符串,該迭代器塊將一次一個地從字符串中提取雙精度值。這會更好地執行方式,並且可能會解決您的內存問題。

+0

我終於決定審查循環。其中有太多的操作。現在它運行良好,但我不得不重新考慮整個事情,所以最少的數據被轉化了。我沒有完全使用你的解決方案,但很明顯,通過閱讀我的方式出了問題,非常感謝。 – Fjodr 2012-01-30 20:03:10