跟網友在部落格上討論效能時提到一個議題--在迴圈中加入try...catch是否會影響效能?

依我的認知,try...catch只有在發生Exception時才會嚴重危害效能,平時正常執行時,我們倒可以"幾乎忘了它的存在"。

不過,我過去似乎還真沒用測試驗證過這一點,既然聊到了,就順手寫幾行Code實測一番:

using System;
using System.Diagnostics;
 
namespace TryCatchCost
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            int RUN_COUNT = 200 * 10000;
            long sum = 0;
            bool flag10K = false;
            //Test 1, no try catch
            sw.Start();
            for (int i = 0; i < RUN_COUNT; i++)
            {
                sum += i;
                if (i == 10000) flag10K = true;
            }
            sw.Stop();
            Console.WriteLine("Test1 Sum={0:N0} Time={1:N0}ms",
                sum, sw.ElapsedMilliseconds);
            //Test 2, try catch
            sw.Reset(); sum = 0;
            sw.Start();
            for (int i = 0; i < RUN_COUNT; i++)
            {
                try
                {
                    sum += i;
                    if (i == 10000) flag10K = true;
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: {0}", e.Message);
                }
            }
            sw.Stop();
            Console.WriteLine("Test2 Sum={0:N0} Time={1:N0}ms",
                sum, sw.ElapsedMilliseconds);
            //Test 3, try catch and one exception
            sw.Reset(); sum = 0;
            sw.Start();
            for (int i = 0; i < RUN_COUNT; i++)
            {
                try
                {
                    sum += i;
                    if (i == 10000)
                        throw new ApplicationException("10K");
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: {0}", e.Message);
                }
            }
            sw.Stop();
            Console.WriteLine("Test3 Sum={0:N0} Time={1:N0}ms",
                sum, sw.ElapsedMilliseconds);
 
            Console.Read();
        }
    }
}

Test1, 2, 3都分別執行200萬次的統計加總,Test2與Test1差別在於Test2中加入try catch,但完全不觸發catch段的流程;Test3則故意觸發一次Exception。為了公平起見,三個測試都加入一列if (i == 10000)。測試數據如下:

Test1 Sum=1,999,999,000,000 Time=17ms
Test2 Sum=1,999,999,000,000 Time=18ms
Error: 10K
Test3 Sum=1,999,999,000,000 Time=46ms

Test1與Test2的執行時間相同,應可推論加入try…catch不影響效能。而即使200萬次只觸發1次例外,Test3的執行時間比Test1, 2慢了一倍以上。算是驗證了推論---try…catch只有在發生Exception時才會影響效能,請安心使用


Comments

# by rico

感謝黑暗大花時間測試,現在開始我會忘了它存在(好比夜用型...XD)~~感恩~~^^

# by Slime Meteor

找到有趣的實驗 : Performance implications of Exceptions in .NET http://www.codeproject.com/KB/exception/ExceptionPerformance.aspx 另外 MSDN 的說法是 : " you only incur the cost when the actual exception is thrown " http://msdn.microsoft.com/en-us/library/ms973839.aspx

# by Evan

感謝,科學的證實,令人"就甘心"...

# by 風星

rico 中的方法一跟三主要成本都是花在 new 一個亂數物件吧! 方法二由於物件拉出來,全透過 GetNext() 取隨機值而已,不需要建立一物件實體,所以成本比起另兩個低非常多。 跟 try-catch 在迴圈內外無關,不過如果發生 Exception 就有關係了,因為在迴圈內如果 catch 沒有任何動作,他還是會繼續下一輪迴圈,如果在迴圈外,會被跳離至 catch block 就不會有下一輪迴圈的執行了!

Post a comment