15

我正在创建一个用于性能测试的库。在其中我生成了Dictionary<Type, X>一次。这些项目当前以随机顺序插入。字典在应用程序生命周期内保持不变。

然后它经常用于查找项目。查找是库中较大的瓶颈之一。

是的,我在微优化,但要学习。我想知道是否有更好的方法来获得查找性能?

更新

我使用 dotTrace 来衡量性能。报告 + dotTrace 在我的家用电脑中,所以我这里没有报告(本来可以在其他地方上传)。

我使用了这里找到的测试: https ://github.com/danielpalme/IocPerformance

字典定义在这里找到:https ://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs

(我上周五创建了容器,不要期望太多)

更新2

性能细分

Dictionary.TryGetValueResolve如果我正确解释了数字,则总共需要 101 毫秒(总共 251 毫秒),即 40.2%。

4

2 回答 2

2

如果类型是编译时定义的,您可以尝试像这样实现它:

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; }
}

只需使用此访问。

var myIntX = ValueFor<int>.X;
于 2012-05-14T10:30:07.263 回答
2

Daniel Palme 的 IoC 容器性能基准(以及其他人的)有点误导,因为该基准从容器中解析了非常浅的对象图(尽管它确实清楚地表明容器之间的性能差异很大)。这是不现实的,因为大多数应用程序(正确使用 DI)将具有包含对象数量的对象图。执行此操作时,只需要解析根对象,并且当容器编写正确时,这意味着Dictionary<T,V>.TryGetValue在大多数情况下(或最多只有几个),您对每个(Web)请求只有一次调用。因此,性能Dictionary<T, V>并不是真正的问题。

我相信Dictionary<T,V>whereTKey的最大System.Type性能成本与生成给定哈希码的性能成本有关Type。每次调用TryGetValueType.GetHashCode()都必须调用。GetHashCode 是虚拟的(不能内联),并且该方法调用 3 个其他虚拟方法。最后,对RuntimeHelpers.GetHashCode(key).

换句话说,您将能够优化性能以编写Type用作键的特定(非通用)字典类,而不是调用Type.GetHashCode()您应该调用RuntimeHelpers.GetHashCode(key).

更新(2013-04-05):

几个月前,我试图提高我维护的 DI 容器的性能,并尝试优化字典部分。我编写了自己的字典,直接调用RuntimeHelpers.GetHashCode(key)(并跳过了虚拟调用),但最终性能提升非常小(在 Palme 的基准测试中约为 1%),我决定恢复这些代码更改。所以我目前的理解是,真正的性能成本Dictionary<Type, X>实际上是内部发生的一切RuntimeHelpers.GetHashCode(key)

于 2012-05-14T12:25:21.673 回答