.NET Core中妙用unsafe減少gc提升字符串處理性能


一、前言

昨天在群里討論怎么樣效率的把一個字符串進行反轉,一般的情況我們都知道,只要對String對象進行操作,
那么就會生成新的String對象,比如"1"+"2" 這樣的操作會生成新的String對象。

二、通正方案

通常我們要反轉一個字符中我們都是使用如下方法:

static string Reverse1(string original)
{
    char[] arr = original.ToCharArray();
    Array.Reverse(arr);
    return new string(arr);
}

這種方式,只是通過將數組反轉的方式重新排列了字符的順序,最終還是要重新生成新的String對象,這樣無疑會在數據量比較大的時候,會增加GC負擔的。

三、unsafe方案

本文主要想講述使用**unsafe**的方式來優化性能,當然在最后面還提到了**c# 7.0**中的新特性來實現相同功能。

unsafe關鍵字表示不安全上下文,該上下文是任何涉及指針的操作所必需的。有關更多信息,請參見不安全代碼和指針(C# 編程指南)。

可以在類型或成員的聲明中使用 unsafe 修飾符。因此,類型或成員的整個正文范圍均被視為不安全上下文。

c#在默認情況下生成的都是安全代碼,即進行了代碼托管(.NET的CLR機制好處之一就是自動進行代碼托管,適時的釋放內存,程序員便不必考慮資源的回收問題),而此時,指針不能出現在安全代碼的編譯條件下。
如果因需要想在c#中使用指針,那么unsafe便是一個通道(當然在使用前,需在項目屬性的生成選項中,選擇“允許不安全代碼”)。

直接上代碼吧:

string hello = "hello world你好";

int len = hello.Length * 2;

fixed (char* strs = hello)
{
    byte* start = (byte*)strs;
    byte* end = start + len - 1;
    byte[] ch = new byte[2];
    if (start != null)
    {
        while (start < end)
        {
            ch[0] = *start;
            ch[1] = *(start + 1);

            *start = *(end-1);
            *(start+1) = *(end);

            start = start + 2;

            *(end - 1) = ch[0];
            *(end) = ch[1];

            end = end - 2;
        }
    }

}

fixed 語句設置指向托管變量的指針並在 statement 執行期間“釘住”該變量。如果沒有 fixed 語句,則指向可移動托管變量的指針的作用很小,因為垃圾回收可能不可預知地重定位變量。C# 編譯器只允許在 fixed 語句中分配指向托管變量的指針。(這句話是機器翻譯的,呵呵)

好了最終的結果就是: hello="好你dlrow olleh" , 但是我們並沒有new String哦!

四、C#7 Ref locals ?

其實對說新的C# 7.0來說,它為我們帶來了新ref關鍵字,來處理本地引用(Ref locals )。

讓我們來開一下腦洞,下面是段成立的代碼:

 

string hello = "hello world你好";
ref char strRef = ref getStringArray(ss, 0);

static ref char getStringArray(char[] str,int index)
{
    return ref str[index];
}

strRef是什么?我們是不是可以通過這樣的方式,來達到與使用指針相同的目地?請繼續關注下一篇文章。

 

同時宣傳一下我的新博客,當然博客園我也會更新的。  http://www.dotnet.ren


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM