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
Dictionary.TryGetValue
takes totally 101ms of Resolve
(total 251ms) which is 40,2% if I've interpreted the numbers correctly.
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)
.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With