.NET 程式最佳化不要僅僅盯著代碼執行時間

來源:互聯網
上載者:User

    其實很多寫.NET程式的開發人員都很喜歡通過一些計時器來看來一程式或代碼的運行效率,的確這樣是可以計算出代碼執行所損耗的時間。但.net程式的最佳化不僅僅在於此.大家知道.net提供自動記憶體回收機制,讓我們不用煩惱記憶體回收問題;同樣.net提供給我們的記憶體配置機制也很出色,因為它能非常快速地幫我們進行記憶體配置工作。當我們在享受吃糖的樂趣的時候,別忘了這東西吃多了很容易把牙齒給搞壞的;同樣.net 回收記憶體的時候同樣也讓難受,當然這些情況不會在你資源充足的時候給你帶來煩惱;不過一但出現他足可以讓你吃不下飯。

    所以最佳化.net程式的時候不要忘了GC這東西,解決他的辦法只有一個就是分析那裡產生記憶體,想盡辦法去產生記憶體的地方給幹了(說得有點粗爆).前段時間瞭解了一個對象序列化組件,測試了一下效能發現其效率真的很出色。測試代碼如下:

            int count = 100000;            KJFObject kobj = new KJFObject();            kobj.Mm = new int[] { 34, 24, 545 };            kobj.Haha = "asfsfasfasfas";            kobj.Bind();            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();            sw.Start();            for (int i = 0; i < count; i++)            {                kobj = new KJFObject();                kobj.Mm = new int[] { 34, 24, 545 };                kobj.Haha = "asfsafsafsafasdfasfasf";                kobj.Bind();            }            sw.Stop();            Console.WriteLine(sw.Elapsed.TotalMilliseconds);            BufferWriter writer = new BufferWriter(Encoding.UTF8);            sw.Reset();            sw.Start();            for (int i = 0; i < count; i++)            {                BObject bobj = new BObject();                bobj.Mm = new int[] { 34, 24, 545 };                bobj.Haha = "asfsafsafsafasdfasfasf";                writer.Reset();                bobj.Save(writer);            }            Console.WriteLine(sw.Elapsed.TotalMilliseconds);

    他的序列化效率比直接代碼方式效率只低了50%,這50%的差距帶的效果就是編寫對象的時候更靈光和代碼更少,這是完全可取的。其實測試結果是偏向於後者,如果細心的朋友一定發現一個問題,BufferWriter是可複用的;如果沒有這種機制的情況那後者是完全輸給前者的。以下是兩個實體的定義

public class KJFObject: IntellectObject    {        private int[] _mm;        [IntellectProperty(0)]        public int[] Mm        {            get { return _mm; }            set { _mm = value; }        }        private string _haha;        [IntellectProperty(1)]        public string Haha        {            get { return _haha; }            set { _haha = value; }        }    }    public class BObject:IMessage    {        private int[] _mm;        public int[] Mm        {            get { return _mm; }            set { _mm = value; }        }        private string _haha;        public string Haha        {            get { return _haha; }            set { _haha = value; }        }        public void Load(BufferReader reader)        {            Mm = reader.ReadInt32s();            Haha = reader.ReadString();        }        public void Save(BufferWriter writer)        {            writer.Write(Mm);            writer.Write(Haha);        }    }

    如果緊緊是這樣效率上的差異,那必然不會選擇手寫代碼來做,因為手寫代碼不好維護,容易出錯特別是在大量成員讀寫順序上.從效率上來說這個組件可以說是完全勝任。當我在做一下步測試的時候發現組件的問題,就是沒有記憶體複用機制;於是用記憶體分析工具分析一下記憶體使用量狀況。發現其記憶體使用量情況有點差,記憶體的開銷有點大,在大並發下其GC壓力估計不少。以下是一個測結果:

從測試結果來看排在前頭的有Enumerator,這東西是怎產生的呢,其實就是我們習慣用Foreach產生的,從執行效率上來說Foreach和for沒多大差異,差別就在記憶體配置和回收上。當然你能通過用for把這個對象的開銷幹了,能就更好的事情.byte[] char[]這些都可以通過複用的給幹了,這樣大頭記憶體開銷基本就沒有了。

    那手寫代碼控制序列化同樣的工作其記憶體使用量又怎樣呢

    從記憶體使用量結果來看其差距還是非常大的,足足有5-6倍的差異,這些記憶體的GC回來在高並發下足可以讓整體處理效能最少有著10%的提升。所以記憶體複用在.net程式最佳化中起著十分重要的作用,只是這種最佳化能體現出來的情境有限;不過當你的產品面對運營的時候發現那就是件比較麻煩的事情,因為這些調整很有可能影響一些核心的地方。當你面對高效能應用的時候別忘了GC這個傢伙,它真是一個要命的東西。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.