0

我读过一些关于 AOP 的文章,它看起来是一个非常有趣和强大的工具。

但是性能呢?

例如,如果我创建一个名为MyMethodAspect. 它会做一件简单的事情——在开始执行具有该属性的方法时,称为包含在我的 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 类是否真的只在编译阶段使用,以后不需要任何额外的性能能力?

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

谢谢

4

1 回答 1

2

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

AOP 框架必须仔细考虑 3 个关键的事情才能更快:

  • fire-time(运行时初始化)
  • 拦截技师
  • 消费者整合

在名义上的使用中,只有拦截机制和消费者集成才是真正重要的,除非您垃圾邮件重新启动您的应用程序。

通常在编译时工作的 AOP 框架没有任何触发时间,并且拦截机制与您真正直接在代码中编写建议类似。这就是为什么它们通常是高效的。

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

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

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

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

消费者集成代表了 AOP 框架的真正缺陷(性能问题)。

编译时往往只有这一点需要管理。这就是为什么大多数时候它们在性能方面更好。

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

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

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

总而言之,请谨慎使用客户端 AOP 接口来定义您的建议,它代表了大多数情况下的实际性能开销。

于 2016-12-12T19:15:19.147 回答