我已经阅读了一些关于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类是否仅在编译阶段才真正使用,之后它不需要任何额外的性能?
我希望你能理解我的问题是什么,我很难解释:)
感谢
答案 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接口来定义您的建议,它代表了大多数情况下的实际性能开销。