Dot Net Perls
C#

ArrayList Use and Boxing

by Sam Allen

Problem

Boxing and unboxing is known to be slow, but we want to examine the issue on our own and look at what happens and how to test the operations. Look at the IL (intermediate language) generated, and try to produce benchmarks and draw some guidelines about the state of the art.

Solution: C#

Design and test a short benchmarking program. Granted, this has elements in common with "reinventing the wheel", but these things are fascinating and the wheel is really important. We will set up some benchmarks that satisfy the following criteria.

What is the code you benchmarked?

I benchmarked a program that adds all the numbers in an ArrayList (of 10,000 items) 10,000 times, and the equivalent List<int> generic. There is some addition in the code, but that is just so the JIT doesn't figure out that the loops are useless. Look at the code here.

static void ExampleBoxing1()
{
    // Unbox a value type.
    long count = 0;
    foreach (object i in _arrayList)
    {
        count += (int)i; // Unboxing occurs here.
    }
}

static void ExampleBoxing2()
{
    // Unbox an object and use part of it.
    long count = 0;
    foreach (object ob in _arrayList2)
    {
        count += ((SomeObject)ob).AnotherThing;
    }
}

static void ExampleGeneric1()
{
    // No unboxing.
    long count = 0;
    foreach (int i in _list)
    {
        count += i;
    }
}

static void ExampleGeneric2()
{
    // No unboxing of generic.
    long count = 0;
    foreach (SomeObject ob in _list2)
    {
        count += ob.AnotherThing;
    }
}

What did the benchmarks reveal?

Unboxing is slow. In fact, it is very slow and will overwhelm the benchmark here. Obviously, we already had heard this, but I saw for myself here, and I feel it is worth sharing. In the following image, the left 2 columns are the results for the ArrayList (unboxing), and the right two are for the generic.

Are there any advantages to the boxing code?

No. Actually, none that I can think of, but I have read that generics may result in my IL generated. However, I was unable to verify this, and the runtime gains here likely will overshadow any of that cost. One thing I want to note is that there is a difference between foreach and for in the ArrayList code, which is demonstrated at the IanWho blog.

Discussion

Generics are far faster than ArrayList on both objects and (especially) values such as int. My guidelines are to always prefer generics unless the code has some quirk that may benefit from ArrayList. Generics are an optimization (see memory figures) that also allow more safety.

© 2008 Sam Allen. All rights reserved.

Ads by The Lounge