2011-02-05 207 views
3

我突然得到了運行在不同機器上的兩個程序的內存異常錯誤,即使它看起來有足夠的內存,它仍然顯示出來。我在程序中創建了多個線程,所以不確定這是否適合這個論壇,但它可能是與Visual Studio有關的其他內容,或者它肯定是內存問題。一個程序在我的桌面上使用2 GB內存的visual studio 2008運行。另一個使用Visual Basic 2008 Express在帶有4 GB RAM的Windows 2003服務器上運行。 現在模塊接受一個大的xml文件,讀入一個字符串,然後拆分並存儲在一個字符串數組中。現在大塊的數量可以達到10000個。現在我知道這很大,但我已經運行了一個多月,從未遇到過這個問題。我注意到的唯一其他可能的相關問題是我的硬盤空間不足,但很快就通過清理解決了問題。哦,是的,我的機器的處理器是雙核2.13 GHZ。 這是一個控制檯程序,它可以創建多個web請求,但只有一個特定的模塊出現內存問題,正如我上面所解釋的那樣。類型'System.OutOfMemoryException'的異常被拋出

Public Shared Function textLoad(ByVal _html As String) As Boolean 
    Try 
      //_html is the filestream that was read in 

     Dim defaultHeading = "xmlns:gnip=""http://www.gnip.com/schemas/2010"" xmlns=""http://www.w3.org/2005/Atom""" 
     Dim header_of_xml As String = "<?xml version=""1.0"" encoding=""utf-8""?>" & vbNewLine & "<entry " & defaultHeading & ">" 
     Dim footer_of_xml As String = "</entry>" 
     Dim entry As String = String.Empty 
     Dim xrs As XmlReaderSettings = New XmlReaderSettings() 
     Dim dupeArray As New ArrayList 
     Dim stringSplitter() As String = {"</entry>"} 

     //split the file content based on the closing entry tag 
     sampleResults = Nothing 
     sampleResults = _html.Split(stringSplitter, StringSplitOptions.RemoveEmptyEntries) 
     entryResults.Clear() 

     If getEntryId(sampleResults) Then 
      // the following loops seem clumsy but I wanted to dedupe the lists to //ensure that I am not adding duplicate entries and I do this by going to the getEntryID //method and extracting the ids and then comparing them below 

      For i As Integer = 0 To sampleResults.Count - 1 
       For j As Integer = 0 To idList.Count - 1 
        If sampleResults(i).Contains(idList.Item(j)) AndAlso Not dupeArray.Contains(idList.Item(j)) Then 
         dupeArray.Add(idList.Item(j)) 
         entry = sampleResults(i) 

我沒看任務管理器,用於識別該程序所使用的資源,這是怎麼回事:

Parser.exe CPU = 34 MEM使用率= 349,500ķ

沒有別的密集運行

編輯_ -

想通了EXAC tly出現問題的原因:

**sampleResults = _html.Split(stringSplitter, StringSplitOptions.RemoveEmptyEntries)** 

任何人都可以注意到這個問題?

+0

這可能屬於對stackoverflow.com,但我沒有足夠的代表投票關閉。 –

+0

@TomasLycken你可以隨時舉報 - >國旗 - >不屬於這裏 - >屬於X. – Sathya

+2

@vbNewbie請提供更多詳細信息 - 這是你正在構建的應用程序嗎?你的系統規格是什麼 - 即處理器,RAM等。 – Sathya

回答

9

Split方法爲返回數組中的每個元素分配一個字符串對象的內存。如果你想遇到內存問題,它會在那一行。由於您一次爲潛在的10,000個大型字符串分配內存,因此在可能分散的堆上分配內存時,您可能會發現它無法找到足夠的連續空間來分配下一個字符串(這會導致在你得到的例外中)。你是否真的需要所有這些字符串?或者你可以做這樣的循環:

  1. 一次只讀一行(或緩衝區)來構建一個字符串。
  2. 當您找到第一個「塊」時停止。
  3. 從大塊中獲取所需的信息。 (我假設你不需要整件事,你只是想從中得到一些東西?)。
  4. 繼續閱讀html(在#1重新啓動),將其讀入相同的字符串變量,以便第一個塊可以進行垃圾回收。

如果你可以用這種方式實現你的解決方案,你的問題應該消失。

4

請注意,OOM並不意味着您沒有使用物理RAM,但是您無法在地址空間中安裝所需大小的新內存塊。

有該

  • 堆碎片許多可能的原因
  • 32位處理的2GB限制
  • 的最大存儲器大小在配置設置

而那麼就有假的OOM例外。例如,對於包括無效參數的廣泛問題,GDI +會返回內存不足錯誤。這些也變成了OOM例外。

+0

所以你認爲這可以通過更改代碼並使用更有效,更有效的邏輯來彌補 – vbNewbie

+0

好吧我想確切地說問題發生的地方 - 在以下行中sampleResults = _html.split(stringsplitter,stringsplitoptions.removeemptyentryies) – vbNewbie

2

您是否嘗試過使用.NET性能計數器運行應用程序時分析內存使用情況?您可以啓動性能監視器(在Windows 2008 R2中位於管理工具>性能監視器下),並在.NET存儲器中爲Gen 0堆大小,第1代堆大小,第2代堆大小和大對象堆大小添加計數器。隨着應用程序的運行,您可以使用這些計數器來查看內存分配的位置。

由於您使用的是字符串,因此考慮超過85,000字節的字符串將分配到大對象堆上很重要。所有其他堆都由垃圾收集器壓縮,但出於性能原因,大對象堆永遠不會被壓縮。這基本上意味着物體在被丟棄時會被GC從LOH中清除,但其餘物體永遠不會從它們在LOH上的原始位置移開。CLR的這種行爲可能導致LOH碎片化並最終導致OOM異常。

下面是一個簡單的例子,說明如何LOH framgentation可以導致OOM異常。假設我們在陸委會有100個單位,我們分配10個單位,然後分配5個單位,剩下85個單位。 CLR必須連續分配內存,所以在我們的例子中,我們現在佔用了LOH的前15個單位。我們試圖爲一個真正的大對象分配86個單位,並且我們得到了一個OOM異常。意識到我們沒有足夠的空間,我們清除了我們第一次分配的10個單位,剩下95個單位。我們再次嘗試分配86個單元,但由於CLR沒有壓縮LOH,並且CLR要求連續86個單元,我們仍然會遇到OOM異常。我們將無法分配我們的86個單位,直到我們清除了第5個單位。這是一個過於簡單化的例子,但是如果你使用Google LOH碎片或者檢查這個article,你可以得到更深入的解釋。

我不能肯定地說,如果這是你遇到的問題,但我肯定會檢查出性能監視器來查看你的內存分配的位置。如果你知道分配字符串或超過85,000字節的其他對象的事實,則嘗試將它們進一步拆分,以使它們遠離LOH。

1

我曾經遇到過這個非常相同的問題。 考慮轉向64位操作系統。 我有一些技巧,以延緩此異常:

1. 最重要的是,當大量使用字符串(尤其是長)工作 使用裁判從一個方法轉移到另一個。 它顯着降低了內存和性能。

2. 您可以使用AppDomain來存儲數據。 這會加倍你的記憶力。

3. 每當你可以 - 而不是創建對象和字符串(WebRequests/Response)使用相同的memoryStream或緩衝區重新。 分配一個最大尺寸possile(甚至* 2最大預期尺寸)。 Stream/StringBuilder/strings/classes/Buffers的分配(使用新的) 扼殺堆。

0

這篇文章可能是有用的,它描述的東西比可以拋出異常:

http://kb.insideofthefuture.com/Assuntos/outofmemoryexception.htm

+3

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分,並提供鏈接如果鏈接的頁面發生變化,僅鏈接的答案可能會失效 – bensiu

+2

現在鏈接被破壞@ bensiu的警告是有先見之明的。 –

相關問題