Kebocoran Memori Aneh dengan serializer XML, kelas baru, dan DataSet

Aplikasi kami tiba-tiba mulai mengalami kebocoran memori. Saya telah berhasil mereproduksinya dengan kode pengujian berikut (DotNet 3.5 atau 4.5, visual studio 2013, windows 7/8 64 bit):

  • XMLserializer dibuat dengan tipe kelas baru (meskipun kelas kosong),
  • Perulangan besar, buat kumpulan data dengan satu tabel data dan satu kolom data. ini kodenya:

    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
    

tapi aku masih belum tahu alasannya.


person Chris Hu    schedule 01.06.2015    source sumber
comment
Selamat datang di JADI! Pertimbangkan untuk sedikit membersihkan format contoh kode Anda sehingga orang dapat mengikutinya dengan lebih mudah. Juga, bagaimana Anda tahu bahwa Anda mengalami kebocoran memori? :)   -  person J0e3gan    schedule 02.06.2015
comment
Tidak ada kebocoran memori di Windows 8. Sistem operasi apa yang Anda gunakan? Program berjalan lama, tetapi memori tidak bertambah di pengelola tugas.   -  person jdweng    schedule 02.06.2015
comment
Saya mengujinya di Windows 7 Enterprise,   -  person Chris Hu    schedule 02.06.2015
comment
Saya mengujinya di Windows 7 Enterprise 64bit, Sp1, penggunaan memori naik sangat cepat di task manager, saya akan mencoba mengujinya lagi di windows 8   -  person Chris Hu    schedule 02.06.2015
comment
Jendela 64 bit 8.1, masalah yang sama.   -  person Chris Hu    schedule 02.06.2015
comment
Jdweng, salah satu rekan saya juga bercerita bahwa dia memang melihat kebocoran tersebut. tetapi saya menemukan dia baru saja memeriksa penggunaan memori seluruh mesin yang terkait dengan kebocoran memori kecil. Setelah dia memeriksa penggunaan memori Proses terkait, Dia memastikan kebocoran itu terjadi.   -  person Chris Hu    schedule 02.06.2015
comment
Dapatkan profiler memori dan lihat apakah bocor atau tidak. Apa yang menyebabkan kebocoran.   -  person Ed Pavlov    schedule 06.06.2015


Jawaban (1)


Memori sedang dikonsumsi oleh rakitan run-time yang dihasilkan secara dinamis yang dibuat di dalam konstruktor XmlSerializer. Dari dokumentasi:

Majelis yang Dihasilkan Secara Dinamis

Untuk meningkatkan kinerja, infrastruktur serialisasi XML secara dinamis menghasilkan rakitan untuk membuat serialisasi dan deserialisasi tipe tertentu.

Artinya, pertama kali Anda membuat XmlSerializer untuk tipe tertentu, refleksi digunakan untuk menghasilkan kode c# yang membuat serialisasi dan deserialisasi tipe dan semua tipe yang direferensikan, yang kemudian dihubungkan dan dimuat ke dalam Penyimpanan. Anda dapat melihat kode sumber referensi yang melakukan hal ini di TempAssembly< /a> kelas. Memuat rakitan dinamis akan menghabiskan memori, dan memori tersebut tidak akan pernah dilepaskan hingga AppDomain dibongkar.

Namun, setelah dibuat, rakitan dinamis di-cache dan digunakan kembali oleh runtime dalam situasi berikut:

Infrastruktur menemukan dan menggunakan kembali rakitan tersebut. Perilaku ini hanya terjadi ketika menggunakan konstruktor berikut:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String).

Jika Anda menggunakan salah satu konstruktor lain, beberapa versi rakitan yang sama akan dihasilkan dan tidak pernah dibongkar, yang mengakibatkan kebocoran memori dan kinerja buruk. Solusi termudah adalah dengan menggunakan salah satu dari dua konstruktor yang disebutkan sebelumnya. Jika tidak, Anda harus menyimpan cache rakitan di Hashtable...

Karena Anda sedang menggunakan konstruktor pertama, rakitan dinamis Anda di-cache dan digunakan kembali, artinya konsumsi memori hanya terjadi satu kali saja selama eksekusi aplikasi Anda < em>untuk setiap jenis root yang Anda buat serial. Selama Anda hanya membuat serial dalam jumlah terbatas, memori yang digunakan oleh rakitan dinamis ini dibatasi dan distabilkan dengan cukup cepat.

(Jika Anda perlu membuat serialisasi jenis dalam jumlah yang mungkin tidak terbatas karena Anda melakukannya, katakanlah, pembuatan kelas dinamis maka penggunaan memori Anda mungkin akan terus meningkat. Namun saya ragu Anda melakukan itu.)

person dbc    schedule 23.06.2015