简体   繁体   English

比词典更快的替代品 <Type, X> ?

[英]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. 在其中我生成一个Dictionary<Type, X>一次。 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. 我用dotTrace来衡量性能。 The report + dotTrace is in my home computer, so I don't have the report here (could have uploaded it somewhere otherwise). 报告+ dotTrace在我的家用电脑中,所以我这里没有报告(否则可能会将其上传到其他地方)。

I used the tests found here: https://github.com/danielpalme/IocPerformance 我使用了这里的测试: https//github.com/danielpalme/IocPerformance

The dictionary definition is found here: https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs 字典定义可在此处找到: 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 UPDATE2

性能细分

Dictionary.TryGetValue takes totally 101ms of Resolve (total 251ms) which is 40,2% if I've interpreted the numbers correctly. 如果我正确地解释了数字, Dictionary.TryGetValue需要101ms的Resolve (总共251ms),这是40.2%。

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;

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). Daniel Palme的IoC容器的性能基准(但也包括其他人)也有点误导,因为基准测试解决了容器中非常浅的对象图(虽然它确实清楚地表明容器之间的性能差异很大)。 This is unrealistic, because most applications (that use DI properly) will have object graphs that contain dosens of objects. 这是不现实的,因为大多数应用程序(正确使用DI)将具有包含对象剂量的对象图。 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). 执行此操作时,只需要解析根对象,并且在正确写入容器时,这意味着在大多数情况下(或者在以下情况下)您将只能单次调用Dictionary<T,V>.TryGetValue per(web)请求大多数只是)。 Because of this, the performance of Dictionary<T, V> is not really an issue. 因此, Dictionary<T, V>的性能并不是真正的问题。

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 . 我认为, TKeySystem.TypeDictionary<T,V>的性能成本的最大部分与为给定Type生成哈希码的性能成本有关。 Every time you call TryGetValue , Type.GetHashCode() has to be called. 每次调用TryGetValue ,都必须调用Type.GetHashCode() GetHashCode is virtual (can't be inlined) and that method calls 3 other virtual methods. GetHashCode是虚拟的(不能内联),该方法调用3个其他虚拟方法。 In the end a static (external) call is made to RuntimeHelpers.GetHashCode(key) . 最后,对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) . 换句话说,您将能够优化性能以编写使用Type作为键的特定(非泛型)字典类,而不是调用Type.GetHashCode()您应该调用RuntimeHelpers.GetHashCode(key)

UPDATE (2013-04-05): 更新(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. 几个月前,我试图提高我维护的DI容器的性能,并且我在优化字典部分。 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. 我编写了自己的字典,直接调用RuntimeHelpers.GetHashCode(key) (并跳过了虚拟调用),但最终性能提升到如此之小(在Palme的基准测试中大约1%),我决定恢复这些代码更改。 So my current understanding is that the real performance cost with Dictionary<Type, X> is actually everything that happens inside RuntimeHelpers.GetHashCode(key) . 所以我目前的理解是,使用Dictionary<Type, X>的实际性能成本实际上是在RuntimeHelpers.GetHashCode(key)中发生的所有事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM