何时执行AOP代码

时间:2013-09-11 08:08:55

标签: performance compilation aop

我已经阅读了一些关于AOP的文章,它看起来像一个非常有趣和强大的工具。

但是性能呢?

例如,如果我创建一个名为MyMethodAspect的方面属性,该怎么办?它会做一件简单的事情 - 在具有该属性的exucting方法的开头称为MyMethodAspect类中包含的代码。例如,写一行文字 - '开始......'

这是基本的例子 - 但是如果在启动方法时执行的逻辑要困难得多。 我是否可以理解,启动方法时执行的代码只编译一次,而后来AOP不需要任何额外的性能?

C#:

public void Do(int x){
Console.WriteLine(x);
}

我认为IL就像(几乎一样):

 public void Do(int x){
    Console.WriteLine(x);
    }

以及方面:

C#:

[MyMethodAspect]
    public void Do(int x){
    Console.WriteLine(x);
    }

所以我想IL就是这样的:

 public void Do(int x){
Console.WriteLine("starting...");
    Console.WriteLine(x);
    }

MyMethodAspect类是否仅在编译阶段才真正使用,之后它不需要任何额外的性能?

我希望你能理解我的问题是什么,我很难解释:)

感谢

1 个答案:

答案 0 :(得分:2)

让我们谈谈性能和AOP实现。

AOP框架必须谨慎地处理3个关键事项:

  • 开火时间(运行时初始化)
  • 拦截机制
  • 消费者整合

在名义使用中,除非您重新启动应用程序,否则只有拦截机制和消费者集成非常重要。

通常,在编译时工作的AOP框架没有任何开火时间,拦截机制类似于您在代码中直接编写建议。这就是为什么它们通常是有效的。

关于运行时AOP框架,它们通常不是真正的AOP模式,因为它们需要代理/工厂模式来拦截方法调用。代理意味着2种类型的开销:包装或消息接收器。在第一种情况下,它是可以接受的,而对于第二种情况,它确实是成本。

编译时和运行时AOP对于消费者集成都有同样的问题:

  • 装箱/拆箱
  • 处理原始代码
  • 您可以定义建议的方式。

需要定义横向代码是合理的。

消费者整合代表了AOP框架的真正陷阱(性能问题)。

编译时间通常只有这一点才能管理。这就是为什么大部分时间他们在表现方面都更好。

我写了“通常”,因为它适用于常见的实现。

在绝对情况下,运行时AOP框架可以做得更好,因为它可以在编织时获得更多信息。实现一个有效的运行时AOP框架更难(不可能?),因为它需要大量未记录的知识来操纵CLR。

经过大量研究,我开发了一种新的.NET运行时AOP框架,它可以破坏规则。 NConcern .NET AOP Framework通过提供独有的拦截机制(基于方法交换)和简单的委托,表达式和ILGenerator的消费者集成来提高效率(甚至超过基于编译时间),以避免装箱/拆箱和不必要的客户端使用准备。例如,大多数时候需要使用反射来知道如何执行建议。许多AOP框架在实际处理中提供元数据,这意味着他们通过准备它们会产生开销。在一个很好的实现(如NConcern提供)中,您可以在真正的处理之前获得这些信息,因为AOP框架为您提供了描述如何生成建议而不是直接使用反射和装箱编码。即使在NConcer的基本界面(直接建议定义)中,您也可以选择是否捕获元数据。

总而言之,要仔细考虑客户端AOP接口来定义您的建议,它代表了大多数情况下的实际性能开销。