Speedy generics
In the Microsoft Press Training Kit for MCTS Exam 70-536, Tony Northrup writes:
I was clued in to the cost of boxing and unboxing by dotTrace, a handy profiler with a ten day trial. It burrowed into my thousand-line mass of code and showed that 85% of the method's runtime was consumed by CompilerServices.NewLateBinding.LateIndexGet and LateGet calls. The next most expensive method was SortedList.get_Item, using only 1% of the overall time, despite being called a third as often as the other two methods combined.
So I dumped my HashTables and ArrayList objects in favor of generic Dictionary(of String, String) and List(of String) objects. With these generics, the late binding was eliminated and the sprightly get_Item now represented 8% of the runtime, while overall performance was nicely improved.
But why are these collections, which require you to specify the datatypes that they contain, called "generics"? It makes sense, in a way. You do have to specify their contents, but generic collections can contain any type, whereas non-generic collections can contain only Objects.
I haven't been able to reproduce the performance benefits of generics; however, according to Microsoft, generics are faster than using casting. In practice, casting proved to be several times faster than using a generic. However, you probably won’t notice performance differences in your applications. (My tests over 100,000 iterations took only a few seconds.) So you should still use generics because they are type-safe.I recently found that using generics offered a significant improvement to a complicated patch of code I'm working on. Here's a simple demonstration.
Dim ht As New Hashtable Dim sw As New System.Diagnostics.Stopwatch sw.Start() For i As Integer = 1 To 10000 For j As Integer = 1 To 10000 If ht.Contains(i) Then ht(i) = j Else ht.Add(i, j) End If Next Next sw.Stop() Console.Write("Hashtable time(ms): " & sw.ElapsedMilliseconds)Average time over six runs was 11157 ms for a debug build and 11305 for a release build, compared to:
Dim sw As New System.Diagnostics.Stopwatch Dim dic As New Dictionary(Of Integer, Integer) sw.Start() For i As Integer = 1 To 10000 For j As Integer = 1 To 10000 If dic.ContainsKey(i) Then dic(i) = j Else dic.Add(i, j) End If Next Next sw.Stop() Console.Write("Generic dictionary time(ms): " & sw.ElapsedMilliseconds)which took 4431 ms in debug and 3610 in release, improvements of 60% and 68% respectively.
I was clued in to the cost of boxing and unboxing by dotTrace, a handy profiler with a ten day trial. It burrowed into my thousand-line mass of code and showed that 85% of the method's runtime was consumed by CompilerServices.NewLateBinding.LateIndexGet and LateGet calls. The next most expensive method was SortedList.get_Item, using only 1% of the overall time, despite being called a third as often as the other two methods combined.
So I dumped my HashTables and ArrayList objects in favor of generic Dictionary(of String, String) and List(of String) objects. With these generics, the late binding was eliminated and the sprightly get_Item now represented 8% of the runtime, while overall performance was nicely improved.
But why are these collections, which require you to specify the datatypes that they contain, called "generics"? It makes sense, in a way. You do have to specify their contents, but generic collections can contain any type, whereas non-generic collections can contain only Objects.