TryCatch的效能測試及Throw的效能測試

  • 4888
  • 0
  • 2011-11-17

TryCatch的效能測試及Throw的效能測試

Dotblogs 的標籤: ,

今天同事忽然說,不要在 Try Catch 太多程式,因為效能會變差!其實這是不完全正確的,事實上,只有在觸發 Catch ex 時,才會造成較大的效能損失,這個在黑暗大的文章都有提過了:

http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/11/14/kb-how-avoidable-try-catch-tortures-your-machine.aspx

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

 

--------
沒什麼特別的~
不過是一些筆記而已