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

C# P/Invoke 與 StringBuilder 效能優化:非託管互操作與字串處理實戰

     編輯:關於C語言

P/Invoke 基礎概念

Platform Invocation Services (P/Invoke) 讓受控碼呼叫非受控 DLL 匯出函式。每次跨越受控/非受控邊界會產生 轉換開銷(Transition/Thunk),估計 10-40 條指令。頻繁呼叫會嚴重影響效能。

效能優化原則

  • 減少呼叫次數:批次處理、陣列參數一次傳遞多筆資料
  • 避免頻繁封送複雜結構:改用 IntPtr 手動配置記憶體、Marshal.Copy 批次複製
  • 啟用 DllImport 最佳化:CallingConvention、CharSet、SetLastError 明確指定
  • 考慮 SuppressUnmanagedCodeSecurity:信任的高頻 API 可略過安全檢查(需極度謹慎)

StringBuilder vs String:字串處理效能實測

using System;
using System.Text;

class Program {
    static void Main() {
        const int Cycle = 10000;
        long tick = Environment.TickCount;

        // String 拼接:每次產生新實例
        string str = null;
        for (int i = 0; i < Cycle; i++) str += i.ToString();
        Console.WriteLine($"String: {Environment.TickCount - tick} ms");

        tick = Environment.TickCount;
        // StringBuilder:內部緩衝區擴展,不產生中間物件
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < Cycle; i++) sb.Append(i);
        Console.WriteLine($"StringBuilder: {Environment.TickCount - tick} ms");

        // String 不變性示範
        string s1 = "A";
        string s2 = s1; // 參考同一物件
        Console.WriteLine(s1); // A
        Console.WriteLine(s2); // A
        s1 = "B"; // s1 指向新物件
        Console.WriteLine(s1); // B
        Console.WriteLine(s2); // A (未變)

        Console.ReadLine();
    }
}

典型輸出(環境差異大,僅供參考量級)

String: 375 ms
StringBuilder: 16 ms
A
A
B
A

String 核心特性總結

特性說明
參考型別儲存在堆積,變數存參考
不可變任何操作(拼接、替換、截取)皆產生新實例
運算子重載==/!= 比較內容值而非參考
驻留池編譯期常量、String.Intern 會共用實例

StringBuilder 最佳實踐

  1. 預估容量:new StringBuilder(estimatedLength) 減少擴容分配
  2. 重用實例:sb.Clear() 或 sb.Length = 0 重設,避免重新分配
  3. 避免 ToString() 多次呼叫:若需多次檢查內容,考慮 sb.ToString() 後快取
  4. 大字串場景:StringBuilder 為首選;簡單拼接 2-3 字串用 + 或 string.Concat 即可

P/Invoke 字串封送陷阱


// 非託管簽章: void NativeFunc(char* buffer, int bufferSize)
// 錯誤:StringBuilder 當 out 參數但未預設容量
[DllImport("Native.dll")] static extern void NativeFunc(StringBuilder buf, int size);

// 正確:預先配置容量
StringBuilder sb = new StringBuilder(256);
NativeFunc(sb, sb.Capacity);
// 或指定 MarshalAs
[DllImport("Native.dll")]
static extern void NativeFunc([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder buf, int size);
  • CharSet.Ansi:單位元組字串(預設),對應 LPStr
  • CharSet.Unicode:雙位元組字串,對應 LPWStr
  • In/Out 屬性明確指定資料流向,避免雙向封送開銷

總結

P/Invoke 與字串處理是效能敏感區域。記住:跨邊界呼叫要少、字串拼接用 StringBuilder、封送明確指定方向與編碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved