首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 程式碼效能優化(一):Finalize 模式與跨界呼叫成本

     編輯:關於C語言

18.4.1 Finalize 模式與 GC 壓力

Object.Finalize 是 .NET 釋放非受控資源的最後防線,但會帶來顯著效能負擔:

  • 具 Finalize 的物件需經過兩輪 GC才能回收(第一輪進入 Finalization Queue,第二輪才真正釋放)。
  • Finalize 執行順序不確定,不保證執行(進程強制結束時)。
  • 大量 Finalize 物件會阻塞 Finalizer 執行緒,導致記憶體暴漲。
  • 物件參考鏈中若有不可回收物件,整條鏈無法 Finalize。

建議模式:Dispose + GC.SuppressFinalize


public class MyResource : IDisposable {
    private bool disposed = false;
    private IntPtr nativeHandle;

    // 公開 Dispose,供使用者主動釋放
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this); // 告訴 GC 不需呼叫 Finalize
    }

    // 受控覆寫點
    protected virtual void Dispose(bool disposing) {
        if (!disposed) {
            if (disposing) {
                // 釋放受控資源
            }
            // 釋放非受控資源
            if (nativeHandle != IntPtr.Zero) {
                NativeMethods.CloseHandle(nativeHandle);
                nativeHandle = IntPtr.Zero;
            }
            disposed = true;
        }
    }

    // 最終保障
    ~MyResource() {
        Dispose(false);
    }
}

優勢

  • 使用者可透過 using 區塊決定性釋放:using (var r = new MyResource()) { ... }
  • 避免 Finalize 額外 GC 週期,大幅降低記憶體壓力。
  • 符合 .NET Framework Design Guidelines 標準模式。

18.4.2 轉換成本

受控與非受控程式碼互呼叫(P/Invoke、COM Interop)每次轉換約 10~40 條指令開銷。

優化策略

  1. 批次化呼叫:將多次小操作合併為單次大操作(如一次寫入大緩衝區而非多次寫入小區塊)。
  2. 減少邊界穿越:在 Managed 端完成資料整理再一次性傳給 Native。
  3. 使用 Blittable 型別:byte、int、double、結構體無需封送,直接複製記憶體。
  4. 固定緩衝區:GCHandle.Alloc(buffer, GCHandleType.Pinned) 避免 GC 移動記憶體,供 Native 直接存取。

實務建議

  • 檢視 IL 或使用 PerfView、dotnet-trace 定位轉換熱點。
  • 封裝 Native API 時,設計粗粒度介面(Chunky API)而非細粒度。
  • 大量資料傳輸考慮 MemoryMappedFile 或 Span<T> 零複製共享。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved