.NET 程序優化不要僅僅盯着代碼執行時間


    其實很多寫.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這個家伙,它真是一個要命的東西。


免責聲明!

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



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