IDictionary<类型 ,对象>的性能与泛型类型属性

发布于 2024-10-04 19:14:39 字数 1160 浏览 5 评论 0原文

编辑:我这个问题基于一个错误的假设 - 我所做的泛型类型实例查找与在运行时创建的泛型类型上执行的工作相同。我的工具中的内容可供编译器访问,因此它可以将它们编译为地址查找。我仍然对 .MakeGenericType 在幕后所做的事情非常感兴趣。

我刚刚对从 IDictionary 获取值和从具有静态属性的泛型类型获取值进行了快速比较。

100000000 次查找的结果:

字典:14.5246952 泛型类型:00.2513280

.NET 在后台使用了什么样的魔力才能如此快速地映射到泛型实例?我本以为必须使用类似于哈希表的东西来查找。也许它会变得紧张……我不知道!你?

这是我的测试工具 - 我确信它充满了错误,所以让我知道什么需要修复!

void Main()
{
    var sw = new Stopwatch();
    var d = new Dictionary<Type, object>() 
    { 
     { typeof(string), new object() },
     { typeof(int), new object() } 

    };
    var stringType = typeof(string);
    var intType = typeof(int);
    sw.Start();
    for (var i = 0; i < 100000000; i++)
    {
        Debug.Assert(d[stringType] != d[intType]);
    }
    sw.Stop();
    sw.Elapsed.Dump();
    sw.Reset();

    Lookup<string>.o = new object();
    Lookup<int>.o = new object();
    sw.Start();
    for (var i = 0; i < 100000000; i++)
    {
        Debug.Assert(Lookup<string>.o != Lookup<int>.o);
    }
    sw.Stop();
    sw.Elapsed.Dump();
}

class Lookup<T>
{
    public static object o;
}

edit: I based this question on a false assumption - that the generic type instance lookups I was doing would be the doinf same work as when done on generic types created at runtime. The ones in my harness are accessible to the compiler so it can compile them into address lookups. I'm still pretty interested in what .MakeGenericType does behind the scenes.

I've just done a quick comparison between getting a value from a IDictionary and getting a value from generic type with a static property.

Results for 100000000 lookups:

Dictionary: 14.5246952
Generic type: 00.2513280

What kind of magic is .NET using in the background to map to the instance of the Generic so quickly? I would have thought something similar to a hashtable would have to be used to lookup. Maybe it gets JITTED... I don't know! Do you?

Here's my test harness - I'm sure it's full of mistakes so let me know what needs fixing!

void Main()
{
    var sw = new Stopwatch();
    var d = new Dictionary<Type, object>() 
    { 
     { typeof(string), new object() },
     { typeof(int), new object() } 

    };
    var stringType = typeof(string);
    var intType = typeof(int);
    sw.Start();
    for (var i = 0; i < 100000000; i++)
    {
        Debug.Assert(d[stringType] != d[intType]);
    }
    sw.Stop();
    sw.Elapsed.Dump();
    sw.Reset();

    Lookup<string>.o = new object();
    Lookup<int>.o = new object();
    sw.Start();
    for (var i = 0; i < 100000000; i++)
    {
        Debug.Assert(Lookup<string>.o != Lookup<int>.o);
    }
    sw.Stop();
    sw.Elapsed.Dump();
}

class Lookup<T>
{
    public static object o;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

刘备忘录 2024-10-11 19:14:39

JIT 编译器知道 static o 变量的地址。它将它分配在加载器堆中。它是泛型类的成员是不相关的。换句话说,解析静态变量的地址不需要运行时查找,它是在编译时完成的。生成的机器代码很简单:

000000f8  mov         eax,dword ptr ds:[02785D0Ch] 
000000fd  cmp         eax,dword ptr ds:[02785D10h] 

注意硬编码地址。

The JIT compiler knows the address of the static o variable. It allocated it in the loader heap. That it is a member of a generic class is not relevant. In other words, resolving the address of a static variable does not require a runtime lookup, it is done at compile time. The generated machine code is trivial:

000000f8  mov         eax,dword ptr ds:[02785D0Ch] 
000000fd  cmp         eax,dword ptr ds:[02785D10h] 

Note the hard-coded addresses.

姐不稀罕 2024-10-11 19:14:39

我认为到泛型的映射是在编译时进行的,而字典在运行时执行查找。

I think that mappings to your generics are made at compile time, whereas dictionary performs lookup in runtime.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文