【问题标题】:Why is reflection computationally expensive? [duplicate]为什么反射计算成本高? [复制]
【发布时间】:2013-05-12 21:06:34
【问题描述】:

显然反射是一个非常广泛的主题,但让我们举一个简单的例子:“is”运算符(A 是 B)。它实际上需要 CLR 做什么?要查看程序集的元数据,请找到类型 A,遍历其继承层次结构并查看 B 是否在其中。

现在,这不是 CLR 的所有标准工作吗?我的意思是,CLR 在运行时一直在非反射代码中进行类型检查。每当您调用方法或为参数赋值时,CLR 必须在运行时检查所分配对象的类型是否与其指定的参数或变量匹配。

那么是什么让反射(我指的是简单的运算符,例如“is”或“as”)相对昂贵?

【问题讨论】:

  • 有编译时和运行时检查,反射涉及运行时检查。
  • “每当你调用方法或为参数赋值时,CLR 必须在运行时检查分配对象的类型是否与其指定的参数或变量匹配。” 这些检查是在编译时完成。在运行时,编译的代码在这方面大多被认为是正确的(如果不是这样,你会得到不同的错误)。
  • 另外:是什么让你相信isas 很贵?
  • 您显然已经意识到这一点,但是反射(至少使用大写的 R)通常意味着不仅仅是简单的类型检查。 is 并不那么昂贵。在正常情况下,它不应该有很大的不同。但如果你广泛使用is(和as),你可能有一个更紧迫的问题需要解决:多态性出错了。
  • @OP 是的,您的错误在于认为类型检查是在运行时完成的。除了强制转换和显式反射之外。

标签: c# .net clr


【解决方案1】:

is 运算符与检索类的类型一样昂贵。最大的区别在于何时产生该成本。在 is 运算符的情况下,当 JIT 编译器在编译代码时从程序集中检索元数据时,就会发生这种情况。这发生在您执行代码之前,因此很可能是您在分析时没有观察到的成本。或者将其视为不可避免的开销,它是。完成后,在循环中使用 is 会非常便宜,因为抖动已将指向类型方法表(也称为“类型句柄”)的指针值直接编译到机器码。无需再次查找类型。

Reflection 不是这样,它不会提前运行。您将测量在磁盘上查找程序集的成本以及在执行程序集文件时从程序集文件中调入元数据的页面错误。这可能是相当大的,磁盘很慢。以及之后再次找到元数据缓存槽的成本。

【讨论】:

  • is 运算符的结果由于多态性而无法在编译时确定。多态性只能在运行时确定。
【解决方案2】:
猜你喜欢
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 2010-09-18
  • 2011-03-24
  • 2013-01-06
相关资源
最近更新 更多