Try Catch Block是否會影響效能?
4 | 20,451 |
跟網友在部落格上討論效能時提到一個議題--在迴圈中加入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 就不會有下一輪迴圈的執行了!