41

I have a number of data classes representing various entities.

Which is better: writing a generic class (say, to print or output XML) using generics and interfaces, or writing a separate class to deal with each data class?

Is there a performance benefit or any other benefit (other than it saving me the time of writing separate classes)?

Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
Roberto Bonini
  • 7,164
  • 6
  • 39
  • 47

12 Answers12

60

There's a significant performance benefit to using generics -- you do away with boxing and unboxing. Compared with developing your own classes, it's a coin toss (with one side of the coin weighted more than the other). Roll your own only if you think you can out-perform the authors of the framework.

Danimal
  • 7,672
  • 8
  • 47
  • 57
  • Which I have done, but my hand-rolled was also generic so go figure. – Joshua Jan 23 '10 at 20:46
  • 10
    Empirical evidence tells me that the supposed performance benefit of using generics is largely theoretical. Strong typing however is a pretty convincing argument to choose generics over their non-generic counterparts. – Captain Sensible Apr 20 '10 at 14:49
22

Not only yes, but HECK YES. I didn't believe how big of a difference they could make. We did testing in VistaDB after a rewrite of a small percentage of core code that used ArrayLists and HashTables over to generics. 250% or more was the speed improvement.

Read my blog about the testing we did on generics vs weak type collections. The results blew our mind.

I have started rewriting lots of old code that used the weakly typed collections into strongly typed ones. One of my biggest grips with the ADO.NET interface is that they don't expose more strongly typed ways of getting data in and out. The casting time from an object and back is an absolute killer in high volume applications.

Another side effect of strongly typing is that you often will find weakly typed reference problems in your code. We found that through implementing structs in some cases to avoid putting pressure on the GC we could further speed up our code. Combine this with strongly typing for your best speed increase.

Sometimes you have to use weakly typed interfaces within the dot net runtime. Whenever possible though look for ways to stay strongly typed. It really does make a huge difference in performance for non trivial applications.

Quonux
  • 2,975
  • 1
  • 24
  • 32
Jason Short
  • 5,205
  • 1
  • 28
  • 45
16

Generics in C# are truly generic types from the CLR perspective. There should not be any fundamental difference between the performance of a generic class and a specific class that does the exact same thing. This is different from Java Generics, which are more of an automated type cast where needed or C++ templates that expand at compile time.

Here's a good paper, somewhat old, that explains the basic design: "Design and Implementation of Generics for the .NET Common Language Runtime".

If you hand-write classes for specific tasks chances are you can optimize some aspects where you would need additional detours through an interface of a generic type.

In summary, there may be a performance benefit but I would recommend the generic solution first, then optimize if needed. This is especially true if you expect to instantiate the generic with many different types.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
Andrew Queisser
  • 1,163
  • 10
  • 20
8

I did some simple benchmarking on ArrayList's vs Generic Lists for a different question: Generics vs. Array Lists, your mileage will vary, but the Generic List was 4.7 times faster than the ArrayList.

So yes, boxing / unboxing are critical if you are doing a lot of operations. If you are doing simple CRUD stuff, I wouldn't worry about it.

Community
  • 1
  • 1
torial
  • 13,085
  • 9
  • 62
  • 89
6

Generics are one of the way to parameterize code and avoid repetition. Looking at your program description and your thought of writing a separate class to deal with each and every data object, I would lean to generics. Having a single class taking care of many data objects, instead of many classes that do the same thing, increases your performance. And of course your performance, measured in the ability to change your code, is usually more important than the computer performance. :-)

Hristo Deshev
  • 907
  • 6
  • 10
5

According to Microsoft, Generics are faster than casting (boxing/unboxing primitives) which is true. They also claim generics provide better performance than casting between reference types, which seems to be untrue (no one can quite prove it).

Tony Northrup - co-author of MCTS 70-536: Application Development Foundation - states in the same book the following:

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 haven't been able to reproduce such performance benefits with generics compared to casting between reference types - so I'd say the performance gain is "supposed" more than "significant".

JohnIdol
  • 48,899
  • 61
  • 158
  • 242
  • I was just reading Tony Northrup's book, that exact page, and ended up here after googling about the performance benefits of generics. The answers to this question seem wildly different - You and Tony both find there is little performance benefit, while others (e.g. Jason Short, above) find a massive performance benefit. I wonder why there is so much difference here? – codeulike Jun 16 '09 at 14:05
  • keep in mind I am not talking about primitives (boxing/unboxing), that is obviously faster with genercis - Microsoft claims that Generics provide better performance than casting between reference types but I am getting quite the opposite result! Have a look at the comments here http://dotnetbutchering.blogspot.com/2008/09/net-generic-perfomance-myth-and-tony.html (my blog) and you'll find my results – JohnIdol Jun 16 '09 at 16:35
  • Without seeing the actual code that Tony used to test, it's hard to argue about this. It is possible that Tony compared built-in generic types (such as `List`) with a non-generic equivalent (such as `StringCollection`) and this comparison does not say much about the performance of generics itself, but rather compares the performance of those two implementations. Casting is quite an expensive operation, so you would normally see a performance improvement when using a generic type (that saves you from casting) over a non-generic type and having to cast constantly. – Steven Aug 04 '11 at 11:34
  • It's fairly easy to test this for yourself. In response to one of the other answers on this question, I wrote a test program (loop adding an item to the list, then reading the just-added item), and I found that List is consistently about 40% faster than ArrayList, no matter how many things are added. I tried with 10, 100, 1000, 1000000 and 100 million, and it's always the same speed benefit for generics... – Orion Edwards Aug 13 '12 at 23:56
3

if you compare a generic list (for example) to a specific list for exactly the type you use then the difference is minimal, the results from the JIT compiler are almost the same.

if you compare a generic list to a list of objects then there is significant benefits to the generic list - no boxing/unboxing for value types and no type checks for reference types.

also the generic collection classes in the .net library were heavily optimized and you are unlikely to do better yourself.

Nir
  • 29,306
  • 10
  • 67
  • 103
3

In the case of generic collections vs. boxing et al, with older collections like ArrayList, generics are a performance win. But in the vast majority of cases this is not the most important benefit of generics. I think there are two things that are of much greater benefit:

  1. Type safety.
  2. Self documenting aka more readable.

Generics promote type safety, forcing a more homogeneous collection. Imagine stumbling across a string when you expect an int. Ouch.

Generic collections are also more self documenting. Consider the two collections below:

ArrayList listOfNames = new ArrayList();
List<NameType> listOfNames = new List<NameType>();

Reading the first line you might think listOfNames is a list of strings. Wrong! It is actually storing objects of type NameType. The second example not only enforces that the type must be NameType (or a descendant), but the code is more readable. I know right away that I need to go find TypeName and learn how to use it just by looking at the code.

I have seen a lot of these "does x perform better than y" questions on StackOverflow. The question here was very fair, and as it turns out generics are a win any way you skin the cat. But at the end of the day the point is to provide the user with something useful. Sure your application needs to be able to perform, but it also needs to not crash, and you need to be able to quickly respond to bugs and feature requests. I think you can see how these last two points tie in with the type safety and code readability of generic collections. If it were the opposite case, if ArrayList outperformed List<>, I would probably still take the List<> implementation unless the performance difference was significant.

As far as performance goes (in general), I would be willing to bet that you will find the majority of your performance bottlenecks in these areas over the course of your career:

  1. Poor design of database or database queries (including indexing, etc),
  2. Poor memory management (forgetting to call dispose, deep stacks, holding onto objects too long, etc),
  3. Improper thread management (too many threads, not calling IO on a background thread in desktop apps, etc),
  4. Poor IO design.

None of these are fixed with single-line solutions. We as programmers, engineers and geeks want to know all the cool little performance tricks. But it is important that we keep our eyes on the ball. I believe focusing on good design and programming practices in the four areas I mentioned above will further that cause far more than worrying about small performance gains.

Jason Jackson
  • 17,016
  • 8
  • 49
  • 74
3

Generics are faster!

I also discovered that Tony Northrup wrote wrong things about performance of generics and non-generics in his book.

I wrote about this on my blog: http://andriybuday.blogspot.com/2010/01/generics-performance-vs-non-generics.html

Here is great article where author compares performance of generics and non-generics:

nayyeri.net/use-generics-to-improve-performance

Andriy Buday
  • 1,959
  • 1
  • 17
  • 40
  • You are referring to MCTS 70-536 aren't you? This is by far the worst computer related book I've read in my career (and I've read quite a few). Not only is it full of silly mistakes and it contains many statements that are plain wrong. Even the published errata list just covers about 10% of the actual errors in the book. – Steven Aug 04 '11 at 11:38
2

If you're thinking of a generic class that calls methods on some interface to do its work, that will be slower than specific classes using known types, because calling an interface method is slower than a (non-virtual) function call.

Of course, unless the code is the slow part of a performance-critical process, you should focus of clarity.

Khoth
  • 13,068
  • 3
  • 28
  • 27
2

See Rico Mariani's Blog at MSDN too:

http://blogs.msdn.com/ricom/archive/2005/08/26/456879.aspx

Q1: Which is faster?

The Generics version is considerably faster, see below.

The article is a little old, but gives the details.

John Gardner
  • 24,225
  • 5
  • 58
  • 76
0

Not only can you do away with boxing but the generic implementations are somewhat faster than the non generic counterparts with reference types due to a change in the underlying implementation.

The originals were designed with a particular extension model in mind. This model was never really used (and would have been a bad idea anyway) but the design decision forced a couple of methods to be virtual and thus uninlineable (based on the current and past JIT optimisations in this regard).

This decision was rectified in the newer classes but cannot be altered in the older ones without it being a potential binary breaking change.

In addition iteration via foreach on an List<> (rather than IList<>) is faster due to the ArrayList's Enumerator requiring a heap allocation. Admittedly this did lead to an obscure bug

ShuggyCoUk
  • 36,004
  • 6
  • 77
  • 101