TryCatch的效能測試及Throw的效能測試
今天同事忽然說,不要在 Try Catch 太多程式,因為效能會變差!其實這是不完全正確的,事實上,只有在觸發 Catch ex 時,才會造成較大的效能損失,這個在黑暗大的文章都有提過了:
http://blog.darkthread.net/post-2009-12-20-try-catch-performance.aspx
然後衍生想起,之前有在點部落看過這篇文章:
http://www.dotblogs.com.tw/larrynung/archive/2011/01/03/20548.aspx
用 Throw 取代 Throw ex,以保留原始錯誤堆疊資訊。於是就興起個念頭,現在電腦等級愈來愈好,效能的損失還有這麼大嗎,以及三種 Throw Exception 的方式,效能差異為何,所以搞出這篇文章。
先用黑暗大的測試程式,我跑出來的數據,顯示有無觸發 Exception,其實還算好:
Test1 Sum=1,999,999,000,000 Time=7ms
Test2 Sum=1,999,999,000,000 Time=8ms
Error: 10K
Test3 Sum=1,999,999,000,000 Time=9ms
黑暗大在他的測試時,200萬次只觸發1次例外,Test3的執行時間比Test1, 2慢了一倍以上(46ms 比 18ms),不過在我手邊的新筆電上跑起來,看來差異就小很多了( 1ms 的差距)。然後我就搞了自己的測試,前三個是測試三種 Throw Exception 十萬次的結果,後兩個是跑一百萬次,一個沒擲回錯誤,一個擲回 100 次 Exception,先來看我電腦跑的結果,再貼程式碼:
Catch ex then throw new excetpion cost time/100000: 4747ms
Catch ex then throw excetpion cost time/100000: 4427ms
Catch ex then only throw cost time/100000: 4454ms
Try catch and not invoke exception cost time/(100*10000): 11ms
Try catch and invoke exception cost time/(100*10000): 16ms
差距真的很小囉,不過當然還是有損失。
Module1.vb
Module Module1
Private Const INT_Constant As Integer = 100000
Sub Main()
Dim sw As New Stopwatch
sw.Reset()
sw.Start()
testThrowNewEx()
sw.Stop()
Console.WriteLine("Catch ex then throw new excetpion cost time/{0}: {1}ms", INT_Constant, sw.ElapsedMilliseconds.ToString)
sw.Reset()
sw.Start()
testThrowEx()
sw.Stop()
Console.WriteLine("Catch ex then throw excetpion cost time/{0}: {1}ms", INT_Constant, sw.ElapsedMilliseconds.ToString)
sw.Reset()
sw.Start()
testThrow()
sw.Stop()
Console.WriteLine("Catch ex then only throw cost time/{0}: {1}ms", INT_Constant, sw.ElapsedMilliseconds.ToString)
sw.Reset()
sw.Start()
testTryCatchNoEx()
sw.Stop()
Console.WriteLine("Try catch and not invoke exception cost time/(100*10000): {0}ms", sw.ElapsedMilliseconds.ToString)
sw.Reset()
sw.Start()
testTryCatchThrowEx()
sw.Stop()
Console.WriteLine("Try catch and invoke exception cost time/(100*10000): {0}ms", sw.ElapsedMilliseconds.ToString)
Console.WriteLine("Test end. ")
End Sub
Public Sub testThrowNewEx()
Dim t As New UsingThrowNewEx
For i As Integer = 1 To INT_Constant
Try
t.GetException()
Catch ex As Exception
'nothing
End Try
Next
End Sub
Public Sub testThrowEx()
Dim t As New UsingThrowEx
For i As Integer = 1 To INT_Constant
Try
t.GetException()
Catch ex As Exception
'nothing
End Try
Next
End Sub
Public Sub testThrow()
Dim t As New UsingThrow
For i As Integer = 1 To INT_Constant
Try
t.GetException()
Catch ex As Exception
'nothing
End Try
Next
End Sub
Public Sub testTryCatchNoEx()
Dim t As New UsingTryCatchAndNoEx
Dim sum As Integer = 0
For i As Integer = 1 To 1000000
Try
t.go(i)
sum += 1
Catch ex As Exception
sum += 1
End Try
Next
End Sub
Public Sub testTryCatchThrowEx()
Dim t As New UsingTryCatchAndThrowEx
Dim sum As Integer = 0
For i As Integer = 1 To 1000000
Try
t.go(i)
sum += 1
Catch ex As Exception
sum += 1
'Console.WriteLine("Exception in here! Count = {0}", i.ToString)
End Try
Next
End Sub
End Module
UsingThrow.vb
Public Class UsingThrow
Public Sub GetException()
Try
Throw New NullReferenceException
Catch ex As Exception
Throw
End Try
End Sub
End Class
UsingThrowEx.vb
Public Class UsingThrowEx
Public Sub GetException()
Try
Throw New NullReferenceException
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
UsingThrowNewEx.vb
Public Class UsingThrowNewEx
Public Sub GetException()
Try
Throw New NullReferenceException
Catch ex As Exception
Throw New ArgumentException("UsingThrowNewEx", ex)
End Try
End Sub
End Class
UsingTryCatchAndNoEx.vb
Public Class UsingTryCatchAndNoEx
Public Sub go(ByVal i As Integer)
Try
If i Mod 100000 = 0 Then
'nothing
Else
'nothing
End If
Catch ex As Exception
'nothing
End Try
End Sub
End Class
UsingTryCatchAndThrowEx.vb
Public Class UsingTryCatchAndThrowEx
Public Sub go(ByVal i As Integer)
Try
'每一萬次丟一個Excepion
If i Mod 10000 = 0 Then
Throw New ApplicationException("oh~")
Else
'nothing
End If
Catch ex As Exception
Throw
End Try
End Sub
End Class
--------
沒什麼特別的~
不過是一些筆記而已