2011-02-05 4 views
3

Я внезапно получаю ошибки исключения памяти для двух программ, работающих на разных компьютерах, и хотя кажется, что памяти достаточно, она все еще появляется. Я создаю несколько потоков в программе, поэтому не уверен, что это подходит для этого форума, но может ли это быть чем-то другим, связанным с визуальной студией или это определенно проблема с памятью. Одна программа работает на моем рабочем столе, используя визуальную студию 2008 с 2 ГБ оперативной памяти. Другой работает на сервере Windows 2003 с 4 ГБ оперативной памяти, используя визуальный базовый 2008 Express. Теперь модуль принимает большой XML-файл, который считывается в строку, а затем разбивается и сохраняется в массиве строк. Теперь количество кусков может быть до 10000. Теперь я знаю, что это большой, но я работаю над этим уже более месяца и никогда не имел проблемы. Единственная другая возможная проблема, которую я заметил, заключалась в том, что у меня не хватило места на моем жестком диске, но это было быстро разрешено с помощью очистки. О да, процессор для моей машины - это дуо-ядро, установленное на 2.13 ГГц. Это консольная программа, которая создает несколько веб-записей, но проблема с памятью возникает в одном конкретном модуле только в том виде, как я объяснял выше.Исключение типа '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 K

ничего более интенсивное работает

Edit _ -

Разобрался exac где возникает проблема:

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

Может ли кто-нибудь заметить что-то не так с этим?

+0

Это, вероятно, принадлежит на stackoverflow.com, но у меня нет достаточно респ голоса, чтобы закрыть. –

+0

@TomasLycken вы всегда можете отметить это -> Флаг -> Здесь не принадлежит -> Принадлежит X. – Sathya

+2

@vbNewbie, пожалуйста, предоставьте более подробную информацию - это приложение, которое вы создаете? Каковы ваши технические характеристики системы - например, процессор, AMount RAM и др. – Sathya

ответ

9

Метод Split выделяет память для строкового объекта для каждого элемента в возвращаемом массиве. Если вы столкнетесь с проблемой памяти, это будет на этой линии. Поскольку вы распределяете память на потенциально 10 000 больших строк сразу, на потенциально фрагментированной куче, неудивительно, что вы можете прийти к точке, где она просто не может найти достаточно непрерывного пространства для выделения для следующей строки (что приведет к в том случае, если вы получаете). Вам действительно нужны все эти строки сразу? Или вы можете сделать что-то вроде этого цикла:

  1. Прочитайте одну строку за раз (или в буфер), чтобы построить строку.
  2. Остановитесь, когда вы нашли первый «кусок».
  3. Получите необходимую информацию от куска. (Я предполагаю, что вам не нужно все это, вы просто заинтересованы в получении чего-то из этого?).
  4. Продолжайте читать html (перезагрузите в # 1), прочитав его в той же строковой переменной, чтобы первый кусок мог получить собранный мусор.

Если вы можете реализовать свое решение таким образом, вы должны исчезнуть.

4

Обратите внимание, что OOM не означает, что вы находитесь вне физической памяти, но вы не можете вставить новый новый блок памяти нужного размера в адресное пространство.

Есть целый ряд возможных причин для этой фрагментации

  • кучного
  • предел 2 Гб 32-битных процесса
  • максимальный размер памяти установлен в конфигурации

И то есть фальшивые исключения OOM. Например, GDI + возвращает ошибки вне памяти для широкого класса проблем, включая недопустимые параметры. Они также превращаются в исключение OOM.

+0

, так как вы думаете, что это можно исправить, изменив код и используя более эффективную, эффективную логику. – vbNewbie

+0

Хорошо, я понял где именно возникла проблема - в следующей строке sampleResults = _html.split (stringsplitter, stringsplitoptions.removeemptyentryies) – vbNewbie

2

Вы пробовали профилировать использование памяти в качестве приложения, использующего счетчики производительности .NET? Вы можете запустить монитор производительности (в Windows 2008 R2 он находится в разделе «Администрирование»> «Монитор производительности») и добавить счетчики в разделе «Память .NET для размера генератора 0», «Размер кучи 1-го уровня», «Размер кучи» Gen 2 и «Большой размер кучи объекта». По мере запуска вашего приложения вы можете использовать эти счетчики, чтобы узнать, где находятся распределения памяти.

Поскольку вы работаете со строками, важно учитывать, что строки размером более 85 000 байт будут распределены по большой кучи объектов. Все остальные кучи уплотняются сборщиком мусора, но по соображениям производительности большая куча объектов никогда не уплотняется. Это в основном означает, что объекты будут очищены от LOH GC, когда они расположены, но остальные объекты никогда не перемещаются из их исходных мест на LOH.Такое поведение CLR может привести к фрагментации LOH и, в конечном счете, к исключениям OOM.

Вот простой пример того, как кадрирование LOH может привести к исключениям OOM. Скажем, у нас есть 100 единиц, доступных на LOH, и мы выделяем 10 единиц, а затем 5 единиц, оставив нам 85 левых. CLR должен постоянно выделять память, поэтому в нашем примере прямо сейчас мы занимаем первые 15 единиц LOH. Мы пытаемся выделить 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 или буфер снова и снова. Выделите номер с максимальным размером (даже * 2 максимальный ожидаемый размер). распределение (с использованием нового) потока/StringBuilder/строк/классов/буферов Suffocate the heap.

0

Эта статья может быть полезна, это описать то, чем может бросить исключение:

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

+3

Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для ссылка. Ответы только на ссылку могут стать недействительными, если связанная страница изменится. – bensiu

+2

Ссылка теперь не работает. @ Предупреждение bensiu было предвестником. –

Смежные вопросы