IDictionary<类型 ,对象>的性能与泛型类型属性类型>
编辑:我这个问题基于一个错误的假设 - 我所做的泛型类型实例查找与在运行时创建的泛型类型上执行的工作相同。我的工具中的内容可供编译器访问,因此它可以将它们编译为地址查找。我仍然对 .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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
JIT 编译器知道 static o 变量的地址。它将它分配在加载器堆中。它是泛型类的成员是不相关的。换句话说,解析静态变量的地址不需要运行时查找,它是在编译时完成的。生成的机器代码很简单:
注意硬编码地址。
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:
Note the hard-coded addresses.
我认为到泛型的映射是在编译时进行的,而字典在运行时执行查找。
I think that mappings to your generics are made at compile time, whereas dictionary performs lookup in runtime.