【问题标题】:What sorts of things should I do to make a performant and robust reflection cache?我应该做哪些事情来制作高性能和强大的反射缓存?
【发布时间】:2008-10-11 08:56:39
【问题描述】:

在 .NET 3.5 中,我将使用 System.Reflection 来使用 AOP(可能在 Castle 的 Windsor 拦截器的上下文中)来执行诸如定义需要在方法级别执行哪些安全操作等事情. 我听说反射的某些部分很慢(我已经阅读了有关它的 MSDN 文章),并且想缓存这些部分(当我更接近生产代码时,无论如何)。我想验证我的方法:

  • 缓存键为 {type} + {区分大小写的方法名称} + {参数类型列表}
  • 缓存键对象可以通过 Equals 操作进行比较
  • 缓存负载是 {MethodInfo} + {方法上定义的自定义属性列表}
  • 缓存通过构造函数注入注入到我的拦截器中
  • 缓存可以维持很长时间(基于我不会编写自修改代码的假设;-))

更新:

我不打算通过反射调用我自己编写的方法;只是(目前)查找我想要注入功能的属性,其中属性定义了要注入的行为。目前,我的拦截器将使用 Castle 的 Windsor IInterceptor 机制,直到我发现更改它的理由。

【问题讨论】:

    标签: c# .net reflection caching


    【解决方案1】:

    显式调用 MethodInfo 确实很慢 - 但如果将其转换为委托,您可以做得更快,更多。例如,请参阅this blog post。当然,这在查找方法等方面无济于事,但是如果您要反复调用该方法,则值得牢记。

    缓存键听起来很容易构建 - 类型和字符串比较好和容易。价值观总是相对简单的:)

    一旦建立,缓存是只读的吗?你能把这些阶段分开,这样你就可以保证在完全构建之前不会被读取吗?如果是这样,您应该能够在没有任何显式锁定的情况下逃脱 - 基本上是从自定义键类型到自定义值类型的字典。

    【讨论】:

    • 目前我认为是的,缓存将是只读的并且永远持久 - 我认为我不会在运行时更改“扩展点在此处”属性-time(虽然被激发的动作可能更加动态)。
    【解决方案2】:

    我同意 Jon 的大部分帖子 - 对字典的一个小注释:从性能的角度来看,您可能希望对此进行基准测试,而不是一个简单的列表。上次我做了一个基准测试(字典与平面列表,检查每个项目直到找到匹配项),分割点(用于读取访问)大约是 150 个项目;在此之下,列表更快(只是通过简单)。但是做你自己的测试......(我没有数字可以证明一种或另一种方式)。

    根据代码,您可以使用泛型进一步拆分数据 - 即缓存,以便类型 T 的所有信息都在一个位置,填充在缓存的静态 ctor 中。这可能会也可能不会,具体取决于架构。

    最后,它可能适合也可能不适合,但现有的 AOP 框架(如 PostSharp)可能有助于简化注入点。

    关于通用点 - (在您的 init 代码中)为 Cache 方法上的方法创建类型化委托将相当容易,以减少它需要扫描的数据量 - 只需一点 Type. MakeGenericType 和 Delegate.CreateDelegate - 在这之后,代码只知道你的 Func<...> 委托,不需要关心实现。

    【讨论】:

      猜你喜欢
      • 2017-07-13
      • 2010-09-06
      • 2016-02-19
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 2017-03-05
      • 2011-04-12
      相关资源
      最近更新 更多