Automatic Memory Management
Automatic memory management ถือเป็นอีกบริการหนึ่งของ Common Language Runtime (CLR) ซึ่งจะให้บริการระหว่าง Execution
Garbage collector (GC) ใน CLR คือผู้ทำหน้าที่จัดสรร (allocation) และการคืน (Release) หน่วยความจำให้กับ Application ในมุมของ ผู้พัฒนานั้นก็หมายความว่าเราไม่ต้องเขียน Code เพื่อจัดการเรื่อง Memory เอง ในระหว่างการพัฒนา Application อีกต่อไป นั่นก็หมายความว่า Automatic memory management ทำให้เรา เป็นการกำจัดปัญหาที่เกิดขึ้นซ้ำซากในเรื่องการจัดการ Memory เช่นการลืมคืน Memory หลังจากที่ใช้ในการสร้าง Object และใช้งานเสร็จแล้ว ซึ่งเป็นที่มาของ Memory leak ที่เรารู้จักกันดี ในบทความนี้จะอธิบายการทำงานของ Garbage Collector ในการจัดสรร(Allocation) และการคืน (Release) Memory ให้กับ Application ว่าทำงานอย่างไร
Allocation Memory
เมื่อเราเริ่มการประมวลผล ครั้งใหม่ CLR จะทำการจอง(Reserve) พื้นที่ต่อเนื่องในหน่วยความจำให้กับการประมวลผล พื้นที่ดังกล่าวเรียกว่า Managed heap.
Managed heap นี้จะเก็บ Pointer ชี้ไปยัง ตำแหน่งที่จะจัดสรรให้กับ Object อันถัดไปใน Heap ซึ่ง Pointer นี้จะชี้ไปที่ Base Address ของ Manage Heap. เมื่อ Application สร้างตัวแปรชนิดที่เป็น Reference type ตัวแรก หน่วยความจำจะถูกจองให้กับตัวแปรตัวนั้นเริ่มที่ Base Address ใน Manage heap แล้วทำการชี้ Point Address ไว้ที่ตำแหน่งถัดจากตัวแปรนี้ หรือ Object นี้ และเมื่อ Application สร้าง Object ตัวต่อไป Garbage collector จะจองพื้นที่ใน Managed heap ต่อจาก Object แรกตรงตำแหน่งที่ Pointer Address ชี้อยู่ แล้ว ขยับ Pointer Address ไปยังตำแหน่งถัดไป ทำอย่างนี้ไปเรื่อย ๆ ตราบใดที่ยังมีพื้นที่เหลืออยู่
การจัดสรร Memory ใน Manage Heap นั้นอาจกล่าวได้ว่า เร็วกว่าการจัดสรรใน Unmanaged memory เพราะว่า การทำใน CLR นั้นเป็นการเพิ่มหรือต่อท้ายพื้นที่ใน Memory และมี Pointer Address ชี้อยู่ อาจกล่าวได้ว่ามีความเร็วเท่ากับการ จัดสรร Memory ใน Stack เลยก็ว่าได้ นอกจากนี้การเข้าถึง Object ที่สร้างขึ้นนั้นก็รวดเร็วเนื่องจากการจัดสรร Memory นั้นเป็นการทำแบบต่อเนื่องกันดังที่ได้กล่าวไปแล้ว มีลักษณะตามภาพด้านล่าง
Releasing Memory
กลไกการ optimizing ของ Garbage collector (GC) จะหาช่วงเวลาที่เหมาะสมเพื่อรวบรวมรายการของ การ Allocations ( ขอใช้คำทับศัพท์นะครับความหมายจะได้ไม่คลาดเคลื่อน ) ตามที่ถูกสร้างขึ้น
เมื่อ GC รวบรวมรายการได้ ก็จะตรวจสอบและ คืน Memory ที่ item ที่ไม่ได้ถูกใช้งานโดยตรวจสอบกับ Root ในแต่ละ Application จะมีกลุ่มของ Root ที่อ้างอิงไปยัง Object ที่สร้างขึ้นและอยู่ ใน Managed heap หรือ ถ้ายังไม่ได้ถูกสร้างขึ้นจะมีค่าเป็น null ใน Application root หนึ่ง ๆ นั้นจะมี static field , local variable และ parameters บน stack ของ thread รวมถึง CPU Register GC Collector สามารถเข้าถึงไปยังรายการของ Active Roots ที่ CLR ดูแลอยู่ และโดยการใช้รายการนี้ สามารถที่จะตรวจสอบ Application root และรายการ object ที่ถูกสร้างขึ้นในระหว่างการประมวลผล ได้ ถ้า Object ใดที่ไม่ได้อยู่ในรายการ ที่เข้าถึงผ่านทาง Application root ได้ GC จะพิจารณาได้ว่า object นั้นไม่ได้ถูกอ้างอิงใช้งานแล้ว และจะทำการคืน Memory ของ ตำแหน่ง object นั้นกลับไปให้เป็น ที่ว่าง
ในขณะการทำ Collection ของ GC มันก็จะทำการตรวจสอบ Managed heap และมองหาพื้นที่ของ address space ที่ถูกจองและไม่ได้ถูกใช้แล้ว หรือเรียกว่าถูกครอบครองด้วย Object ที่ไม่สามารถเข้าถึงได้ เนื่องจากไม่ได้มีการอ้างอิงใช้งานแล้ว เมื่อพบก็จะทำการที่เรียกว่า Compact Object ที่เข้าถึงได้(reachable objects) ใน memory โดยการ ขยับ ลงไปทับเพื่อให้พื้นที่ว่างของ Managed heap เป็นพื้นที่ที่ต่อเนื่องกัน เป็นผืนเดียวกัน ไม่ให้เป็น พื้นที่ ย่อย ๆ เล็ก เมื่อ Reachable Object ถูก compact แล้ว GC ก็จะทำการปรับตำแหน่งของ pointer ให้ถูกต้องกับตำแหน่งใหม่และ Application root สามารถเข้าถึง object ได้ถูกต้อง
การทำ Memory compact นั้นจะทำก็ต่อเมื่อ GC Collection ตรวจพบว่ามี Unreachable objects จำนวนมากพอ หรือ เข้าขั้นวิกฤติแล้วเท่านั้น ถ้า objects ทั้งหมด ใน Managed heap ยังคงอยู่ในสภาพคล่อง ก็ยังคงไม่จำเป็นต้องทำ Memory Compact.