泛型型別效率測試

在接觸物件(Object)觀念後,都會談到boxing及unboxing的動作,以Visual Basic來說,就是像使用CType()來轉換型別的動作,而且大多數都會談到boxing及unboxing會影響效能,所以都會建議盡量使用「泛型型別」。

不過經過以下測試後,效率應該不能說是使用泛型型別的理由!理由應該是「安全型別」,就像我們常看到的舉例:ArrayList及ArrayList(Of T)、IList或IList(Of T),也就是說ArrayList、IList是個什麼型別都可以包含進去的陣列。假設我程式是在做數值運算,但你放了一個「Hello World!」ArrayList、IList是接受的,這稱「不安全型別」。

而ArrayList(Of T)與IList(Of T)就不同,在宣告時可以指定任意型別給ArrayList(Of T)與IList(Of T),也就是那個T,例如:ArrayList(Of Integer)、IList(Of String),這樣宣告之後,當你在使用時,Visual Studio會自動幫你除錯,不用等到建置之後再來除錯,例如你在ArrayList放了一個「Hello World!」的字串,但ArrayList的宣告只能放Integer,所以或Visual Studio都能很明確找出問題!

泛型型別 V.S 非泛型型別


以下使用主控台應用程式測試:
  1. 新增「主控台應用程式」
  2. 新增一個類別,使用Object來進行處理
  3. 新增一個類別,使用泛型來進行處理
  4. 在主控台應用程式撰寫測試程式碼

測試環境

軟體:
  • XP SP3
  • Visual Studio 2008
  • .Net Framework 2 (3.5 SP1)
硬體:
  • CPU:賽揚 2.0
  • RAM:2 GB
ps:我的家中的硬體算舊且效能平平,都測不出有很大的差異,如果硬體新一點,我看差異更小。

類別Obj(使用Object)

Public Class Obj
    Public _v1 As Object
    Public _v2 As Object
    Public Sub New(ByVal v1 As Object, ByVal v2 As Object)
        _v1 = v1
        _v2 = v2
    End Sub
End Class

類別Gen(使用泛型)

Module Module1

    Sub Main()
        Dim i As Integer = 0
        Dim v1 As String
        Dim v2 As String

        ' st:Star Time
        Dim st As DateTime = Now
        ' boxing、unboxing1百萬次,兩個數變共2百萬次
        For i = 0 To 1000000
            Dim oa As New Obj(1, 2)
            v1 = CType(oa._v1, String)
            v2 = CType(oa._v2, String)
        Next
        'et:End Time
        Dim et As DateTime = Now

        Console.WriteLine("Obj1:{0}", (et - st).ToString)


        st = Now
        ' 泛型型別1百萬次,兩個數變共2百萬次
        For i = 0 To 1000000
            Dim ga As New Gen(Of String, String)("1", "2")
            v1 = ga._v1
            v2 = ga._v2
        Next
        et = Now

        Console.WriteLine("Gen1:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 2000000
            Dim oa As New Obj(1, 2)
            v1 = CType(oa._v1, String)
            v2 = CType(oa._v2, String)
        Next
        et = Now

        Console.WriteLine("Obj2:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 2000000
            Dim ga As New Gen(Of String, String)("1", "2")
            v1 = ga._v1
            v2 = ga._v2
        Next
        et = Now

        Console.WriteLine("Gen2:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 3000000
            Dim oa As New Obj(1, 2)
            v1 = CType(oa._v1, String)
            v2 = CType(oa._v2, String)
        Next
        et = Now

        Console.WriteLine("Obj3:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 3000000
            Dim ga As New Gen(Of String, String)("1", "2")
            v1 = ga._v1
            v2 = ga._v2
        Next
        et = Now

        Console.WriteLine("Gen3:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 4000000
            Dim oa As New Obj(1, 2)
            v1 = CType(oa._v1, String)
            v2 = CType(oa._v2, String)
        Next
        et = Now

        Console.WriteLine("Obj4:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 4000000
            Dim ga As New Gen(Of String, String)("1", "2!")
            v1 = ga._v1
            v2 = ga._v2
        Next
        et = Now

        Console.WriteLine("Gen4:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 5000000
            Dim oa As New Obj(1, 2)
            v1 = CType(oa._v1, String)
            v2 = CType(oa._v2, String)
        Next
        et = Now

        Console.WriteLine("Obj5:{0}", (et - st).ToString)

        st = Now
        For i = 0 To 5000000
            Dim ga As New Gen(Of String, String)("1", "2!")
            v1 = ga._v1
            v2 = ga._v2
        Next
        et = Now

        Console.WriteLine("Gen5:{0}", (et - st).ToString)
    End Sub

End Module

測試數據


Obj1:00:00:01.7968750
Gen1:00:00:00.1562500
Obj2:00:00:03.7343750
Gen2:00:00:00.2812500
Obj3:00:00:05.5000000
Gen3:00:00:00.4218750
Obj4:00:00:07.2968750
Gen4:00:00:00.5468750
Obj5:00:00:09.1093750
Gen5:00:00:00.6875000

我們以最後那個5百萬次的測試來看,中間有兩個變數,所以共進行了一千萬次,很明顯的,泛型型別的效率比需boxing、unboxing的效率快很多倍,但也看的出來.Net Framework在型別處理上是「非常快速」。

結論


我想很少有一支程式必須進行一千萬次的boxing與unboxing,平常的影響連可能連0.1秒都不到。數據證明一切,泛型能提供的率效是高於一般非泛型的多倍,但此差距只有在非常大量(千萬次以上)才明顯,但泛型能帶來型別安全才是我們主要考量因素。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。