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

1、前言

昨天在羣裏討論怎麼樣效率的把一個字符串進行反轉,通常的狀況咱們都知道,只要對String對象進行操做,
那麼就會生成新的String對象,好比"1"+"2" 這樣的操做會生成新的String對象。程序員

2、通正方案

一般咱們要反轉一個字符中咱們都是使用以下方法:編程

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

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

3、unsafe方案

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

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

能夠在類型或成員的聲明中使用 unsafe 修飾符。所以,類型或成員的整個正文範圍均被視爲不安全上下文。性能

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

直接上代碼吧:spa

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哦!指針

4、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

相關文章
相關標籤/搜索