【发布时间】:2010-09-30 19:32:10
【问题描述】:
我们已经开始使用 spring aop 来处理我们应用程序的横切方面(目前是安全和缓存)。
我的经理担心这项技术的性能影响,尽管他完全了解其好处。
我的问题,你有没有遇到过使用aop(特别是spring aop)引入的性能问题?
【问题讨论】:
标签: spring performance aop spring-aop
我们已经开始使用 spring aop 来处理我们应用程序的横切方面(目前是安全和缓存)。
我的经理担心这项技术的性能影响,尽管他完全了解其好处。
我的问题,你有没有遇到过使用aop(特别是spring aop)引入的性能问题?
【问题讨论】:
标签: spring performance aop spring-aop
问题问了11年,看看这种情况有多堕落。
示例:绝大多数人认为在某个方法上放置一个简单的@Transactional spring java 注解并让 spring 在调用者和被调用者代理组件之间架起一座桥梁是可以且正常的。现在他们有 20 多个不可调试的“神奇”代码堆栈帧。 JIT 编译器很快就被超过了,无法再尝试内联,或者最终导致大量生成的类导致内存膨胀。
在这个“框架用户”的时代,懒惰是没有限制的。难怪微不足道的 http 调用的 e2e 时间从 100 毫秒缩短到 10 秒。难怪你需要 2GB 来运行一个糟糕的 servlet 容器,而这个容器曾经运行在 128MB 中。并且不要让我开始记录异常堆栈跟踪的成本......
【讨论】:
理论上,如果你使用 AOP 做你可以用硬耦合做的事情,那么没有性能问题,没有开销,也没有额外的方法调用,除非你什么都不做。 AOP 框架为您提供了一种方法来消除硬耦合并分解您的横切关注点。
在实践中,AOP Framework 可以引入 3 种类型的开销:
更多详情可以参考when-is-aop-code-executed。
请注意如何实现建议,因为横向代码是装箱/拆箱和反射的诱惑(在性能方面很昂贵)。
如果没有 AOP 框架(硬耦合您的横切关注点),您可以更轻松地开发假设的建议(专用于每种处理),而无需装箱/拆箱和反射。
您必须知道,大多数 AOP 框架不提供完全避免装箱/拆箱和反射的方法。
我开发了一个来应对大部分缺失的需求,集中在 3 件事上:
你可以在这里找到我的开源项目:Puresharp API .net 4.5.2+之前NConcern .NET AOP Framework
【讨论】:
我在当前项目的批处理中使用了 Spring AOP 来事务管理数据库。
起初,我们认为不会有性能问题,但我们没有考虑到我们调用数据库数千次的方程式。 aop 中的一个方面调用不会对性能产生太大影响,但将其乘以数千倍,事实证明,由于这些额外的方法调用,新系统比旧系统更差。
我会说 aop 是一个很好用的系统,但请注意有多少方法调用被添加到您的应用程序中
【讨论】:
如果您为切面使用某个框架,则可能会出现一些性能问题。接下来,如果您在某个框架之上创建抽象,并且切面处理是从框架完成的,那么很难找出与性能问题 。如果你真的关心性能和更关心小时间片,我建议编写自己的方面。没有人想重新发明轮子,但有时更好的是最好的。你可以编写自己的 AOP 联盟抽象实现。
【讨论】:
你有没有想过一个 AOP 工具可以在需要时在运行时向对象添加方面? .net 有一个“使用动态装饰器向对象添加方面”(http://www.codeproject.com/KB/architecture/aspectddecorator.aspx)。我相信你可以为 Java 写一个类似的。
【讨论】:
如果要考虑性能,我们使用AspectJ 效果很好。
因为它使用字节码编织(编译时间与运行时差别很大),所以它是目前最快的 AOP 框架之一。见:AOP Benchmarks
【讨论】:
只要您控制您的 AOP,我认为它是有效的。无论如何,我们确实遇到了性能问题,所以根据自己的推理,我们并没有完全控制;)这主要是因为任何编写方面的人都完全了解所有其他,这一点很重要> 系统中的各个方面以及它们如何相互关联。如果你开始做“聪明”的事情,你可以瞬间超越自己。在一个大型项目中做一些聪明的事情,很多人只能看到系统的一小部分,这在性能方面可能是非常危险的。这个建议可能在没有 AOP 的情况下也适用,但是 AOP 可以让您以一些真正优雅的方式自爆。
Spring 还使用代理来进行范围操作,那是一个很容易导致不希望的性能损失的领域。
但鉴于你有控制权,AOP 唯一真正的痛点是对调试的影响。
【讨论】:
如果您使用的是基于代理的 AOP,那么您所说的每个应用方面都会有 1 个额外的 Java 方法调用。那里的性能影响可以忽略不计。唯一真正关心的是代理的创建,但这通常只在应用程序启动时发生一次。 SpringSource 博客对此有一篇很棒的文章:
http://blog.springsource.com/2007/07/19/debunking-myths-proxies-impact-performance/
【讨论】:
当我使用它时,我没有 - 但是我的应用程序不是你的应用程序。
如果您将它用于在非常紧凑的循环中使用的调用,则机会会显着影响性能。如果它只是用于每个请求检查一次安全性并缓存各种内容,我看不出它有多重要 - 但这就是为什么您应该对 您的应用程序进行分析和基准测试。
我意识到“用你的应用衡量”可能不是你想要的答案,但它很可能是你猜到的答案:)
【讨论】: