Garbage Collection

ฉลองมงคล วันเกษม 650710072

Garbage Collection(GC) คือ เทคนิคการจัดการหน่วยความจำที่ใช้ใน .NET Framework ใน C# จะมีหน้าที่ในการปลดปล่อยหน่วยความจำที่ไม่ได้ใช้แล้วโดยอัตโนมัติ เพื่อเพิ่มประสิทธิภาพการใช้หน่วยความจำ

ซึ่งจะทำงานบน Managed Heap เสมอ ซึ่งเป็นพื้นที่ในหน่วยความจำที่ใช้จัดสรรให้กับออบเจ็กต์ ขณะรันโปรแกรม เมื่อมีการสร้างออบเจ็กต์ใหม่ ออบเจ็กต์จะถูกจัดเก็บในหน่วยความจำ heap

ตามปกติแล้ว Garbage Collection จะถูกเรียกใช้โดยอัตโนมัติ แต่ก็สามารถเรียกผ่านเมธอด GC.Collect ได้เช่นกัน

Phases in Garbage Collection

การทำงานของ GC จะมีทั้งหมด 3 ขั้นตอน

  1. Marking Phase ระบบจะสร้าง List ของออบเจ็กต์ที่ยังคงถูกใช้งานออบเจ็กต์ที่โปรแกรมไม่สามารถเข้าถึงได้แล้วจะถูกลบออกจาก heap

  2. Relocating Phase ระบบจะอัปเดตการอ้างอิงของออบเจ็กต์ที่อยู่ใน List เพื่อให้การอ้างอิงชี้ไปที่ตำแหน่งใหม่ ที่ออบเจ็กต์จะถูกย้ายไปในขั้นตอนถัดไป

  3. Compacting Phase ปลดปล่อยพื้นที่หน่วยความจำของออบเจ็กต์ที่ไม่ใช้งาน และย้ายออบเจ็กต์ที่ยังใช้งานอยู่ไปที่ส่วนท้ายของ heap

เพื่อเพิ่มประสิทธิภาพของ Garbage Collection จึงทำการแบ่ง heap ออกเป็นหลาย Generations

Heap Generations in Garbage Collection

หน่วยความจำ heap ถูกแบ่งออกเป็น 3 generations เพื่อให้สามารถจัดการออบเจ็กต์ที่มีช่วงเวลาการใช้งานต่างกันได้อย่างเหมาะสม โดยระบบ Optimization Engine จะเลือกว่าออบเจ็กต์จะถูกย้ายไปยัง generations ไหน

  • Generations 0 ใช้เก็บออบเจ็กต์ที่มีอายุการใช้งานสั้น และเมื่อพื้นที่หน่วยความจำใน Gen 0 เต็มแล้วแอปพลิเคชันพยายามสร้างอ็อบเจ็กต์ใหม่ CG จะดำเนินการรวบรวมเพื่อเพิ่มพื้นที่ที่อยู่สำหรับอ็อบเจ็กต์ และเริ่มการตรวจสอบอ็อบเจ็กต์ใน Gen 0 แทนที่จะตรวจสอบอ็อบเจ็กต์ทั้งหมดใน heap

  • Generations 1 เก็บออบเจ็กต์ที่รอดจากการ CG ใน Gen 0 ทำหน้าที่เป็นพื้นที่กันชนระหว่างออบเจ็กต์อายุสั้นและอายุยาว หาก Gen 0 ไม่สามารถเรียกคืนหน่วยความจำได้เพียงพอเพื่อให้แอปพลิเคชันสามารถสร้างอ็อบเจ็กต์ใหม่ได้จะทำการ CG ใน Gen1 กับ Gen0 และส่งออบเจ็กต์ที่กำลังใช้งานไปยัง Gen2

  • Generations 2 เก็บออบเจ็กต์ที่รอดจากการ CG ใน Gen1 ซึ่งออบเจ็กต์เหล่านี้จะมีอายุการใช้งานยาวนาน เช่น static data

Conditions for a garbage collection

เงื่อนไขที่จะทำให้ GC ทำงาน

  1. มีหน่วยความจำเหลือน้อย

  2. โปรแกรมใช้หน่วยความจำมากเกินที่มี

  3. มีการเรียกใช้เมธอด GC.Collect

ตัวอย่างการเรียกใช้ GC ใน C#

using System;

namespace GCCollectIntExample
{
    class MyGCCollectClass 
    {
        private const long maxGarbage = 1000;  // จำนวนสำหรับสร้างวัตถุ

        static void Main()
        {
            MyGCCollectClass myGCCol = new MyGCCollectClass();
            
            // แสดงจำนวนสูงสุดของ generation
            Console.WriteLine("The highest generation is {0}", GC.MaxGeneration);

            myGCCol.MakeSomeGarbage(); //ใช้ฟังก์ชันสร้างออบเจกต์ที่ไม่ใช้งาน

            // ตรวจสอบว่าออบเจกต์ myGCCol ถูกเก็บใน generation ใดใน heap
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

            // แสดงจำนวนหน่วยความจำที่ถูกใช้ในระบบปัจจุบัน.
            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

            // บังคับให้ GC เก็บขยะเฉพาะ generation 0
            GC.Collect(0);

            // ตรวจสอบว่าออบเจกต์ myGCCol อยู่ใน generation ใดหลังการเก็บขยะ 
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

            // เรียกการเก็บขยะทุก generation
            GC.Collect(2);

            // ตรวจสอบ generation และหน่วยความจำอีกครั้งหลังจากการเก็บขยะ
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));
            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
            Console.Read();
        }

        void MakeSomeGarbage(){
            Version vt;
            for(int i = 0; i < maxGarbage; i++)
            {
                vt = new Version();
            }
        }
        
    }
}

Garbage Collection in C,Java,Python

ในภาษาอื่น GC มีการทำงานที่แทบจะเหมือนกัน หรือบางภาษาอาจจะไม่มีเลย อย่างเช่น

ภาษา C

ในภาษา C ไม่มีระบบ GC จึงต้องจัดสรรพื้นที่ด้วยตนเองโดยใช้ฟังก์ชัน free() คืนหน่วยความจำที่เคยจองไว้จากฟังก์ชัน malloc(), calloc() ใช้ในการจองหน่วยความ และฟังก์ชัน realloc() ปรับขนาดหน่วยความจำ

ตัวอย่างการใช้ free() ในภาษา C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
   char *name;
   name = (char *) calloc(strlen("TutorialsPoint")+1, sizeof(char));
   strcpy(name, "TutorialsPoint");

   if(name  == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name);
      free(name);
   }
}

เมื่อจบโค้ด หน่วยความจำที่จัดสรรให้กับตัวชี้ char * จะถูกยกเลิกการจัดสรร

ภาษา Python

ใน Python มี GC เหมือนใน C# แต่ Python จะมีการทำงานอีกแบบเรียกว่า Reference counting จะเป็นการนับจำนวนอ้างอิงที่กำลังชี้วัตถุนั้นอยู่ ถ้าจำนวนอ้างอิงเป็น 0 จะทำการคืนพื้นที่ของวัตถุนั้น

ตัวอย่างการใช้ GC ใน python

import gc

def create_data():
    data = dict(x=range(10)) # ข้อมูลถูกสร้างและอ้างอิงภายในฟังก์ชันนี้เท่านั้น

create_data()
gc.collect() # แนะนำให้ GC ทำงานเพื่อกำจัดข้อมูลที่ไม่ถูกใช้งาน

print(gc.garbage) # แสดงข้อมูลที่ถูก GC กำจัดไป

ภาษา Java

ใน Java การ CG จะคล้ายกับใน C# แต่ในการแยก heap จะเรียกต่างกัน คือ

  1. Young Generation ใช้เก็บอ็อบเจกต์ที่สร้างขึ้นใหม่ แบ่งเป็น 2 ส่วน Eden เป็นที่ที่อ็อบเจกต์ใหม่ถูกสร้างขึ้น และ Survivor 2 แห่ง ใช้จัดการกับอ็อบเจกต์ที่รอดจากการ CG บ่อยๆ เมื่อพื้นที่เต็มจะทำการ Minor Collection คือการ CG ในรุ่นนี้เท่านั้น และวัตถุที่รอดจากการ CG หลายครั้งจะไปอยู่ใน Old Generation

  2. Old Generation เก็บวัตถุที่รอดมาจาก Young Generation และเมื่อหน่วยความจำในรุ่นนี้เต็มแล้ว จะเกิด Major Collection คือการ CG ทั้ง 2 Generation

ตัวอย่างการใช้ GC ในภาษา Java

public class GarbageDemo {
    public static void main(String[] args) {
        String data = new String("Hello, World!"); // ข้อมูลถูกสร้างขึ้น
        data = null; // ไม่อ้างอิงถึงข้อมูลอีกต่อไป
        System.gc(); // แนะนำให้ GC ทำงาน
        // ช่วงเวลานี้ GC อาจทำงานเพื่อกำจัด 'Hello, World!' ออกจากหน่วยความจำ
    }
}

Silde Presentation

Video Presentation

Reference

GeeksforGeeks. (n.d.). Phases in Garbage Collection. GeeksforGeeks. https://www.geeksforgeeks.org/garbage-collection-in-c-sharp-dot-net-framework/

Microsoft. (n.d.). Heap Generations and Conditions. Microsoft Learn. https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals

Microsoft. (n.d.). ตัวอย่างการเรียกใช้ GC ใน C#. Microsoft Learn. https://learn.microsoft.com/en-us/dotnet/api/system.gc?view=net-8.0&viewFallbackFrom=net-8.0%5C

Tutorialspoint. (n.d.). ภาษา C. Tutorialspoint. https://www.tutorialspoint.com/cprogramming/c_memory_management.htm

GeeksforGeeks. (n.d.). ภาษา Python. GeeksforGeeks. https://www.geeksforgeeks.org/garbage-collection-python/

Oracle. (n.d.). ภาษา java. Oracle Documentation. https://docs.oracle.com/en/java/javase/17/gctuning/garbage-collector-implementation.html#GUID-C2CA24AD-DC01-4B31-A868-F7DAC7E3BF4D

Expert Programming Tutor. (n.d.). ตัวอย่างการเรียกใช้ GC ใน Python และ java.Expert Programming Tutor. https://expert-programming-tutor.com/tutorial/article/KE000462_What_is_Garbage_Collection_In_the_way_of_programming_how_useful.php

Last updated