Object Vs Generic Performance

by Damien Dennehy
c# logo

I happened to be leafing through one of the earlier chapters of a self-paced book for the MCP exam 70-536 (which sadly has been deprecated, though I still intend to finish it), when I came across a comment from Tony Northrup about the difficulties in benchmarking object and generic performance.

I’ve heard the same argument while studying the generic elements of both Java and C# – generics increase performance, but the increase is so minimal that it’s essentially unnoticeable.

Well, where’s the fun in leaving it at that?

Consider the following two classes, Obj and Gen. Both have the same functionality, but Gen uses generics.

public class Obj
{
    public Object t;
    public Object u;
 
    public Obj(object _t, object _u)
    {
        this.t = _t;
        this.u = _u;
    }
}
public class Gen<T, U>
{
    public T t;
    public U u;
 
    public Gen(T _t, U _u)
    {
        this.t = _t;
        this.u = _u;
    }
}

Lets declare an instance of both and perform a little string value check on both our objects.

Obj obj = new Obj("A", 0);
if (((string)(obj.t)).Equals("A"))
{
    obj.t = 100;
}
Gen<string, int> gen = new Gen<string, int>("A", 0);
 
if (gen.t.Equals("A"))
{
    gen.u = 100;
}

I know it’s a silly example, but you will notice that the Obj class has two additional tasks must be performed before the code will compile; the string value must be boxed and unboxed.

I put both of these declarations in a loop and ran it 100,000 times.
The result actually surprised me; the Obj loop took 7 seconds to run, while the Gen loop took 3 seconds to run.

I then repeated these tests and the results are consistency clear on my machine:  generics offer a 40-50% performance over boxing and unboxing objects. The problem however, is that the difference only becomes apparent if you are either working with more than 10,000 objects at once, or performing thousands of conversions within a handful of objects.

Time elapsed for 1 million Object iterations: 49 milliseconds.
Time elapsed for 1 million Generic iterations: 25 milliseconds.

Time elapsed for 100 million Object iterations: 4526 milliseconds.
Time elapsed for 100 million Generic iterations: 2342 milliseconds.

Time elapsed for 1000 million Object iterations: 45.33 seconds.
Time elapsed for 1000 million Generic iterations: 24.36 seconds.

Damien Dennehy