Странная утечка памяти с сериализатором XML, новым классом и набором данных

В нашем приложении внезапно началась утечка памяти. Я успешно воспроизвел его со следующим тестовым кодом (DotNet 3.5 или 4.5, Visual Studio 2013, Windows 7/8 64 бит):

  • XMLserializer, созданный с типом нового класса (даже пустой класс),
  • Большой цикл, создайте набор данных с одной таблицей данных и одним столбцом данных. вот код:

    Imports System.Xml
    Imports System.Xml.Serialization
    Module Module1 
      Sub Main()
          Dim x As XmlSerializer
          x = New XmlSerializer(GetType(tClass))    ' needed for reproduce leak  
          Dim ds As DataSet
          For i As Integer = 0 To 1000000
             For j As Integer = 0 To 1000
                ds = New DataSet
                ds.Tables.Add("tb1").Columns.Add("dssd")
             Next
          Next
      End Sub
    End Module
    Public Class tClass  ' empty class
    End Class
    

но я до сих пор не знаю причину.


person Chris Hu    schedule 01.06.2015    source источник
comment
Добро пожаловать в СО! Подумайте о том, чтобы немного подчистить форматирование вашего примера кода, чтобы людям было легче следовать ему. Кроме того, как узнать, что у вас есть утечка памяти? :)   -  person J0e3gan    schedule 02.06.2015
comment
Нет утечки памяти в Windows 8. Какую операционную систему вы используете? Программа работает долго, но память в диспетчере задач не увеличивается.   -  person jdweng    schedule 02.06.2015
comment
Я тестирую его под Windows 7 Enterprise,   -  person Chris Hu    schedule 02.06.2015
comment
Я тестировал его под 64-битной Windows 7 Enterprise, Sp1, использование памяти очень быстро растет в диспетчере задач, я попробую еще раз протестировать его в Windows 8.   -  person Chris Hu    schedule 02.06.2015
comment
64-битное окно 8.1, та же проблема.   -  person Chris Hu    schedule 02.06.2015
comment
Jdweng, один из моих коллег, также сказал мне, что видел утечку. но я обнаружил, что он только что проверил использование всей памяти машины, что связано с небольшой утечкой памяти. После того, как он проверил использование памяти соответствующим процессом, он подтвердил, что утечка происходит.   -  person Chris Hu    schedule 02.06.2015
comment
Получите профилировщик памяти и посмотрите, есть ли утечка или нет. Что вызывает утечку.   -  person Ed Pavlov    schedule 06.06.2015


Ответы (1)


Память потребляется динамически генерируемыми сборками времени выполнения, созданными внутри конструктора XmlSerializer. Из документации:

Динамически генерируемые сборки

Для повышения производительности инфраструктура сериализации XML динамически создает сборки для сериализации и десериализации указанных типов.

Это означает, что первый раз, когда вы создаете XmlSerializer для определенного типа, отражение используется для создания кода C#, который сериализует и десериализует тип и все типы, на которые ссылаются, которые затем связываются и загружаются в объем памяти. Вы можете увидеть справочный исходный код, который делает это, в TempAssembly< /а> класс. Загрузка динамической сборки потребляет память, и эта память никогда не освобождается до AppDomain выгружается.

Однако после создания динамическая сборка кэшируется и повторно используется средой выполнения в следующих ситуациях:

Инфраструктура находит и повторно использует эти сборки. Это происходит только при использовании следующих конструкторов:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String).

При использовании любого из других конструкторов создается несколько версий одной и той же сборки, которые никогда не выгружаются, что приводит к утечке памяти и снижению производительности. Самое простое решение — использовать один из двух ранее упомянутых конструкторов. В противном случае вы должны кэшировать сборки в Hashtable...

Поскольку вы используете первый конструктор, ваша динамическая сборка кэшируется и используется повторно, а это означает, что потребление памяти является одноразовым событием во время выполнения вашего приложения < em>для каждого корневого типа, который вы сериализуете. Пока вы сериализуете только конечное число типов, память, используемая этими динамическими сборками, ограничена и стабилизируется довольно быстро.

(Если вам нужно сериализовать потенциально неограниченное количество типов, потому что вы делаете, скажем, динамическая генерация классов, то использование памяти может увеличиваться. Но я сомневаюсь, что вы это делаете.)

person dbc    schedule 23.06.2015