Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faster alternative than Dictionary<Type, X>?

I'm creating a library which I'm performance testing. In it I generate a Dictionary<Type, X> once. The items are currently inserted in a random order. The dictionary remains unchanged during the application lifetime.

It's then frequently used to lookup items. The lookup is one of the larger bottlenecks in the library.

Yes, I'm micro-optimizing, but to learn. I'm wondering if there are a better way to get lookup performance?

Update

I've used dotTrace to measure the performance. The report + dotTrace is in my home computer, so I don't have the report here (could have uploaded it somewhere otherwise).

I used the tests found here: https://github.com/danielpalme/IocPerformance

The dictionary definition is found here: https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs

(I created the container last friday, don't expect too much)

Update2

Performance breakdown

Dictionary.TryGetValue takes totally 101ms of Resolve (total 251ms) which is 40,2% if I've interpreted the numbers correctly.

like image 582
jgauffin Avatar asked May 14 '12 07:05

jgauffin


2 Answers

The performance benchmark for IoC containers from Daniel Palme (but those of others as well) is a bit misleading, since the benchmark resolves very shallow object graphs from the container (although it does show clearly that the performance differences between the containers are big). This is unrealistic, because most applications (that use DI properly) will have object graphs that contain dosens of objects. When doing this, only the root object needs to be resolved, and when the container is written properly, this means you will only have a single call to Dictionary<T,V>.TryGetValue per (web) request in most situations (or at most just a few). Because of this, the performance of Dictionary<T, V> is not really an issue.

I believe that biggest part of the performance cost of Dictionary<T,V> where TKey is System.Type, has to do with the performance cost of generating a hash code for the given Type. Every time you call TryGetValue, Type.GetHashCode() has to be called. GetHashCode is virtual (can't be inlined) and that method calls 3 other virtual methods. In the end a static (external) call is made to RuntimeHelpers.GetHashCode(key).

In other words, you would be able to optimize performance to write a specific (non generic) dictionary class that uses Type as a key and instead of calling Type.GetHashCode() you should call RuntimeHelpers.GetHashCode(key).

UPDATE (2013-04-05):

A few months back I tried to improve the performance of the DI container I maintain and I played with optimizing the dictionary part. I wrote my own dictionary that directly called RuntimeHelpers.GetHashCode(key) (and skipped the virtual calls) but in the end the performance gains where so small (around 1% in Palme's benchmarks) that I decided to revert these code changes. So my current understanding is that the real performance cost with Dictionary<Type, X> is actually everything that happens inside RuntimeHelpers.GetHashCode(key).

like image 159
Steven Avatar answered Sep 24 '22 00:09

Steven


If the type is compile-time defined, you may try to implement it like this:

static class ValueFor<T>
{
  // you get another field per type T
  public static X X { get; private set; }

  internal static SetUpValue(X value) { X = value; }
}

Just access using this.

var myIntX = ValueFor<int>.X;
like image 34
Stefan Steinegger Avatar answered Sep 25 '22 00:09

Stefan Steinegger