當前位置: 妍妍網 > 碼農

.NET中的記憶體管理和垃圾回收,優秀碼農必備

2024-06-19碼農

記憶體管理和垃圾回收是 .NET 開發的基本方面,對於構建高效且可伸縮的軟體應用程式非常重要。在這篇文章中,我們將討論堆疊和堆記憶體,探索記憶體分配機制,並了解 .NET 中的垃圾回收。

了解堆疊和堆記憶體

堆疊記憶體

堆疊是用於執行程式程式碼和儲存方法呼叫幀、局部變量和函式參數的記憶體區域。堆疊上的記憶體以後進先出 (LIFO) 方式進行管理。

voidExampleMethod()
{
int localVar = 10; // Local variable stored on the stack
}

在這裏,變量儲存在堆疊上,當方法結束時,其記憶體會自動釋放。localVarExampleMethod

堆記憶體

堆是用於動態分配記憶體(如物件和陣列)的記憶體區域。堆上的記憶體由垃圾回收器手動或自動管理。

classMy class
{
publicint MyProperty { get; set; }
}
voidExampleMethod()
{
My class obj = newMy class(); // Object allocated on the heap
obj.MyProperty = 20;
}

在這裏,物件儲存在堆上,其記憶體由垃圾回收器管理。obj

.NET 中的記憶體分配

值型別與參照型別

在 .NET 中,型別被分類為值型別或參照型別。值型別儲存在堆疊中,而參照型別儲存在堆中,對它們的參照儲存在堆疊中。

voidExampleMethod()
{
intvalue = 10; // Value type stored on the stack
My class reference = newMy class(); // Reference type stored on the heap
}

.NET 中的垃圾回收

垃圾回收基礎知識

垃圾回收是自動回收不再使用的物件占用的記憶體的過程。.NET 采用分代垃圾回收方法,其中物件根據其年齡劃分為幾代。

classProgram
{
staticvoidMain()
{
My class obj = newMy class();
// Code using 'obj'
// When 'obj' is no longer referenced, it becomes eligible for garbage collection
}
}

垃圾回收會定期發生,或者當系統確定堆記憶體不足時發生。在垃圾回收期間,垃圾回收器遍歷所有活動參照,標記可存取物件,並為無法存取的物件解除記憶體分配。

垃圾回收中的幾代人

.NET 利用三代進行垃圾回收:第 0 代、第 1 代和第 2 代。物件從第 0 代開始,並根據其生存情況晉升到更高世代。

  • **第 0 代(第 0 代):**這是最年輕的一代,包含短暫的物體。記憶體分配從這裏開始。垃圾回收器在此代中頻繁執行,以快速從不再需要的物件中回收記憶體。收集 Gen 0 通常非常快,因為它涉及的物件較少。

  • **第 1 代(第 1 代):**在第 0 代垃圾回收中幸存下來的物件將提升為第 1 代。這一代充當短壽命和長壽命物件之間的緩沖區。收集第 1 代的頻率低於第 0 代,但仍旨在有效地回收記憶體。

  • **第 2 代(第 2 代):**此生成包含長期存在的物件,例如靜態數據和長時間使用的物件。就效能而言,收集第 2 代是最昂貴的,因為它涉及堆的更大一部份。因此,這一代垃圾回收器的執行頻率較低。

  • Generational Collection 的工作原理

  • **物件推廣:**當物件在其當前一代的垃圾回收中幸存下來時,它將提升到下一代。例如,Gen 0 中在集合中幸存下來的物件將移動到 Gen 1。

  • **世代掃描:**垃圾收集器對不同的世代執行不同型別的清掃。Gen 0 集合是次要集合,而 Gen 2 集合是涉及更全面的記憶體管理任務的主要集合。

  • 讓我們考慮一個例子,看看物件是如何在幾代人之間移動的。

    usingSystem;
    classProgram
    {
    staticvoidMain()
    {
    // Create object in Generation 0
    My class obj1 = newMy class();
    // Perform some operations
    DoWork();
    // Force a Gen 0 garbage collection
    GC.Collect(0); // Collects Generation 0
    Console.WriteLine("Gen 0 collection completed.");
    // Create more objects
    My class obj2 = newMy class();
    // Perform some more operations
    DoMoreWork();
    // Force a Gen 1 garbage collection
    GC.Collect(1); // Collects Generation 1 and Generation 0
    Console.WriteLine("Gen 1 collection completed.");
    // Create long-lived object
    My class obj3 = newMy class();
    // Simulate application running
    RunApplication();
    // Force a Gen 2 garbage collection
    GC.Collect(2); // Collects Generation 2, Generation 1, and Generation 0
    Console.WriteLine("Gen 2 collection completed.");
    }
    staticvoidDoWork()
    {
    // Allocate some temporary objects
    for (int i = 0; i < 100; i++)
    {
    My class tempObj = newMy class();
    }
    }
    staticvoidDoMoreWork()
    {
    // Allocate more temporary objects
    for (int i = 0; i < 100; i++)
    {
    My class tempObj = newMy class();
    }
    }
    staticvoidRunApplication()
    {
    // Simulate long-running operations
    for (int i = 0; i < 1000; i++)
    {
    My class tempObj = newMy class();
    }
    }
    }
    classMy class
    {
    publicint MyProperty { get; set; }
    }











    使用分代垃圾回收的最佳實踐

    1. **最小化長期物件:**設計應用程式以最大程度地減少長期物件的數量。這降低了第 2 代收集的頻率和成本。

    2. **正確處理物件:**實作介面和use語句,確保及時釋放非托管資源。IDisposableusing

    3. **避免大型物件分配:**大型物件直接分配在大型物件堆 (LOH) 中,並在第 2 代收集期間收集。最大程度地減少大型物件分配,以減少對第 2 代集合的影響。

    classResourceHolder : IDisposable
    {
    privatebool disposed = false;
    publicvoidUseResource()
    {
    if (disposed)
    {
    thrownewObjectDisposedException("ResourceHolder");
    }
    // Use the resource
    }
    publicvoidDispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }
    protectedvirtualvoidDispose(bool disposing)
    {
    if (!disposed)
    {
    if (disposing)
    {
    // Release managed resources
    }
    // Release unmanaged resources
    disposed = true;
    }
    }
    ~ResourceHolder()
    {
    Dispose(false);
    }
    }



    記憶體管理和垃圾回收是 .NET 開發的重要組成部份,會影響應用程式效能和可伸縮性。透過套用最佳實踐,我們可以最佳化記憶體使用、提高應用程式效能並構建高效的 .NET 應用程式。透過這篇文章,我們探討了 .NET 中的記憶體管理和垃圾回收。

    如果你喜歡我的文章,請給我一個贊!謝謝