หน่วยความจำรั่วไหลแปลก ๆ ด้วย XML serializer คลาสใหม่และชุดข้อมูล

แอปพลิเคชันของเราเริ่มมีหน่วยความจำรั่วกะทันหัน ฉันทำซ้ำได้สำเร็จด้วยรหัสทดสอบต่อไปนี้ (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
ยินดีต้อนรับสู่ SO! ลองทำความสะอาดการจัดรูปแบบของตัวอย่างโค้ดเล็กน้อยเพื่อให้ผู้คนสามารถติดตามได้ง่ายขึ้น นอกจากนี้คุณรู้ได้อย่างไรว่าคุณมีหน่วยความจำรั่ว? :)   -  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
ฉันทดสอบโดยใช้ Windows 7 Enterprise, Sp1 แบบ 64 บิต การใช้หน่วยความจำเพิ่มขึ้นอย่างรวดเร็วในตัวจัดการงาน ฉันจะลองทดสอบอีกครั้งใน Windows 8   -  person Chris Hu    schedule 02.06.2015
comment
windows 8.1 64 บิต ปัญหาเดียวกัน   -  person Chris Hu    schedule 02.06.2015
comment
Jdweng เพื่อนร่วมงานคนหนึ่งของฉันก็บอกฉันด้วยว่าเขาเห็นรอยรั่ว แต่ฉันพบว่าเขาเพิ่งตรวจสอบการใช้งานหน่วยความจำเครื่องทั้งหมดซึ่งหน่วยความจำรั่วนั้นสัมพันธ์กันเล็กน้อย หลังจากที่เขาตรวจสอบการใช้งานหน่วยความจำของ Processe ที่เกี่ยวข้อง เขาก็ยืนยันว่ามีการรั่วไหลเกิดขึ้น   -  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