使用AOP的性能影响

48

我们已经开始使用Spring AOP来处理应用程序中的横切关注点(目前是安全性和缓存)。

我的经理担心这种技术会对性能产生影响,尽管他完全理解其好处。

我的问题是,您是否遇到过由AOP引入的性能问题(特别是Spring AOP)?

9个回答

38
只要你对AOP有控制权,我认为它是有效的。我们确实遇到了性能问题,所以按照我的推理,我们并没有完全掌控;这主要是因为编写方面的人必须完全理解系统中所有其他方面的内容及其相互关系。如果你开始做“聪明”的事情,你很快就会被自己蒙在鼓里。在一个由许多只看到系统小部分的人组成的大型项目中做聪明的事情可能会非常危险,会影响性能。这个建议可能也适用于没有使用AOP的情况,但是AOP使你有机会以一些真正优雅的方式误伤自己。
Spring还使用代理进行范围操纵,这是一个容易导致不希望出现的性能损失的领域。
但是,只要你有控制权,AOP唯一真正的痛点就是调试的影响。

29
如果性能是一个问题,我们使用 AspectJ 可以取得很好的效果。因为它使用字节码编织(编译时与运行时有很大的区别),所以它是最快的 AOP 框架之一。参见:AOP 基准测试

2
存档版本仍然可在此处获取:https://web.archive.org/web/20150520175004/https://docs.codehaus.org/display/AW/AOP+Benchmark - kara

21

我使用它时没有问题,但是我的应用和你的应用可能不一样。

如果你在一个非常紧密的循环中使用它进行调用,那么很有可能会对性能产生显著的影响。如果它只是被用来每个请求检查一次安全性并缓存各种东西,我认为它不太可能有显著的影响,但这就是为什么你应该测试和基准测试“你自己”的应用程序。

我知道“用你自己的应用程序测试”可能不是你想要的答案,但这很可能是你猜到的答案 :)


1
是的,确实如此。我希望在争论为什么基准测试不是必需时,我能够提供这篇文章的链接。 :-) - LiorH

7

2
真的吗?为什么我在调试时看到堆栈跟踪中有这么多方法调用(约5个)? - LiorH
你能贴出堆栈跟踪吗?我可能是错误的并忘记了有几个额外的调用进入反射 API 以便代理调用目标。你正在使用 JDK 还是 CGLIB 代理? - cliff.meyers
@LiorH 这取决于应用的方面数量。如果有多个建议,则可能会有多个方法调用。这个 图表可以帮助理解这种情况。 - Raman Sahasi
博客链接非常有帮助!感谢分享。 - mindreader
每个AOP包装调用堆栈中大约有5个方法调用,最终以Java反射Method.invoke()调用结束。我认为这可能是Cliff所指的。无论如何,如果这5个调用的成本大约为500纳秒,则对于基本项目(如事务)不必担心。对于大多数应用程序,每个HTTP请求的代理数量都可以接受。 - Charlie Reitzel

1
理论上,如果你使用AOP来做硬耦合所能做的事情,就没有性能问题、额外开销和多余的方法调用,除非你无意义地进行编织。AOP框架为您提供了一种消除硬耦合并因此实现交叉关注点的方法。
实际上,AOP框架可能会引入三种类型的开销:
  • 运行时间
  • 拦截机制
  • 消费者集成(开发建议的方式)
更多详情请参考when-is-aop-code-executed
只需小心如何实现建议,因为横切代码很容易出现装箱/拆箱和反射(在性能方面代价高昂)。
没有AOP框架(硬耦合您的交叉关注点),您可以更轻松地开发预设的建议(针对每个处理),而不需要装箱/拆箱和反射。
您必须知道,大多数AOP框架都不能完全避免装箱/拆箱和反射。
我开发了一个框架以响应大多数缺失需求,集中于三件事:
  • 易于使用(轻量级,易学习)
  • 透明(无需破坏代码即可包含)
  • 高效(没有装箱/拆箱,没有反射在名义用户代码中和良好的拦截机制)

您可以在这里找到我的开源项目:Puresharp API .net 4.5.2+之前是NConcern .NET AOP Framework


0

如果您正在使用某个框架来处理方面,可能会出现一些性能问题。接下来,如果您在某个框架上创建抽象,并且方面处理是从框架中完成的,则很难找到与性能问题相关的问题原因。如果您真的关心性能和小时间片更关心,我建议编写自己的方面。没有人想要重新发明轮子,但有时为了更好而言,这可能是最好的选择。您可以编写AOP联盟抽象的自己的实现。


0

您是否曾经想过,有一种AOP工具可以在您需要时在运行时向对象添加方面?.Net上已经有了这样一个工具 "Add Aspects to Object Using Dynamic Decorator" (http://www.codeproject.com/KB/architecture/aspectddecorator.aspx)。我相信你也可以为Java编写类似的工具。


0

我在当前项目中的批处理过程中使用了Spring AOP来进行事务管理数据库。

起初,我们认为不会出现性能问题,但是没有考虑到我们要调用数据库数千次。 AOP中的一个方面调用不会对性能产生太大影响,但将其乘以数千倍后,结果显示新系统比旧系统更差,因为这些额外的方法调用。

我认为AOP是一个很好的系统,但请注意您的应用程序中添加了多少方法调用。


0

11年后,看看这种情况是如何堕落的。

例如:绝大多数人认为在某个方法中放置一个简单的@Transactional spring java注释,并让spring在调用方和被调用方代理组件之间建立桥梁是可以的和正常的。现在他们有了20多个堆栈帧的不可调试的“魔术”代码。JIT编译器被迅速超越,不能再尝试内联,或者最终导致内存膨胀,产生大量生成的类。

在这个“框架用户”时代,懒惰没有界限。难怪微不足道的http调用的端到端时间从100毫秒变成了10秒。难怪你需要2GB才能运行一个糟糕的servlet容器,而以前只需要128MB。更不用说日志异常堆栈跟踪的成本了...


我在这里读到了Gold.. 很不错。 - kris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接