1. 程式人生 > >Unity :優化字串操作產生的GC

Unity :優化字串操作產生的GC

前言:

最近被要求改關於字串操作中的GC,比如:數字轉文字、字串拼接等。一般來講有的可以避免,但有的很難避免。比如Number To String的操作,總歸是寫在邏輯的硬需求裡面的(等級、時間、飄血等)。

如上圖所示,這個是Int32.ToString的時候產生的GC,其他的數值轉文字也差不多一個情況。即便呼叫其他的API,最終都會走到這邊一步,一個String.InternalAllocateStr就會產生約42B的GC出來。當然這個是可以考慮作為優化的點,但是這個方法屬於C#底層了,我們需要對String進行擴充來避免他的GC情況出現。

這個時候,通過朋友的介紹,發現了一個叫ZString的東西,他的出現就是為了避免這種GC的問題,於是就開心地拿來測試了一下。

ZString:

關於ZString的介紹和原始碼見下面的連結, 這裡就不贅述了。

1、使用:

這個ZString的使用方法較為麻煩,自然不能像C#的String那麼自如。例如一個將Int轉為字串的操作,需要這麼寫:

                using (ZString.Block())
                {
                    int number = 16578187;
                    ZString zStr = number;
                    string str2 = zStr.ToString();
                }

對的,他在操作的時候要先把這個東西進行Block操作,而出了這個作用域它的值有可能會被改變。

注意:不可使用ZString作為類的成員變數,不建議在Using作用域中寫超大For迴圈。

首次呼叫時會初始化類,分配各種空間,建議遊戲啟動時呼叫一次using(ZString.block()){}

//使用方式:
// 1.當update每幀重新整理標籤顯示,或者該字串是短時間使用的則使用如下方式:
        using (ZString.Block())
        {
            ZString a="hello world";
            a.text=a
        }
// 此方式設定的string值位於深拷貝快取中,一定時間可能會改變。

//2.比如路徑,或者面板上常駐的字串。需要常駐的則需要intern一下在作用域外使用

    using (ZString.Block())
        {
            ZString a="Assets/";
            ZString b=a+"prefabs/"+"/solider.prefab";
            a.path=b.Intern();
        }
//此方式設定的string值位於intern表中,遊戲執行期間不會改變。

2、效率測試:

string和ZString的NumberToString對比:

string :總計1ms,8.6KB GC;

ZString:總計約ms,0GC;

字串拼接測試:

String:    總計0.48ms,8.6 kb GC;

ZString:  總計2.4ms,0 GC;

結論:

這個ZString算是所有的字串補充方案裡面優化得最好的了,但是比起string來單說速度而言有不小的差距。在進行NumberToString操作的時候,其速度是原生String的1/3;而在進行字串拼接的時候,速度降到1/6 。string即便是在有40B的GC的情況下,其總體速度還是要快上不少。

但好在沒有GC,所以還是各位看自己的專案情況使用吧。