代码之家  ›  专栏  ›  技术社区  ›  Peter Mounce

我应该做什么样的事情来创建一个性能良好且健壮的反射缓存?

  •  2
  • Peter Mounce  · 技术社区  · 16 年前

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

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

    更新:

    我并不打算通过我自己写的东西反射来调用方法;只是(目前)在我想要注入功能的方法上查找属性,属性定义了要注入的行为。我的拦截器现在将使用Castle的windsor-iInterceptor机制,直到我发现更改它的原因。

    2 回复  |  直到 16 年前
        1
  •  3
  •   Jon Skeet    16 年前

    显式地调用一个MethodInfo确实很慢-但是你可以做很多, 许多的 如果将其转换为委托,则速度更快。见 this blog post 例如。当然,这在查找方法等方面没有帮助,但是如果您要重复调用该方法,那么需要记住这一点。

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

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

        2
  •  1
  •   Marc Gravell    16 年前

    我同意乔恩的大部分帖子——一个小纸条是字典:从性能的角度来看,你可能想把这个和一个简单的列表作为基准。上一次我做基准测试(字典和简单列表,检查每个项目直到找到匹配项),分界点(用于读取访问)大约是150个项目;低于这个分界点,列表更快(只是简单)。但是做你自己的测试…(我没有可以用来证明这一点的数字)。

    根据代码的不同,您可能可以使用泛型进一步拆分数据,即缓存,以便类型t的所有信息都位于一个位置,并填充在静态ctor for cache中。这可能是可能的,也可能是不可能的,这取决于体系结构。

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

    是通用点-在缓存方法上(在in it代码中)创建一个方法的类型化委托非常容易,可以减少需要扫描的数据量-只需要一点type.makeGenericType和delegate.createDelegate-在这一点之后,代码只知道您的func<…>委托,不需要ca关于实施。