【问题标题】:Performance impact of using aop使用 aop 的性能影响
【发布时间】:2010-09-30 19:32:10
【问题描述】:

我们已经开始使用 spring aop 来处理我们应用程序的横切方面(目前是安全和缓存)。

我的经理担心这项技术的性能影响,尽管他完全了解其好处。

我的问题,你有没有遇到过使用aop(特别是spring aop)引入的性能问题?

【问题讨论】:

    标签: spring performance aop spring-aop


    【解决方案1】:

    问题问了11年,看看这种情况有多堕落。

    示例:绝大多数人认为在某个方法上放置一个简单的@Transactional spring java 注解并让 spring 在调用者和被调用者代理组件之间架起一座桥梁是可以且正常的。现在他们有 20 多个不可调试的“神奇”代码堆栈帧。 JIT 编译器很快就被超过了,无法再尝试内联,或者最终导致大量生成的类导致内存膨胀。

    在这个“框架用户”的时代,懒惰是没有限制的。难怪微不足道的 http 调用的 e2e 时间从 100 毫秒缩短到 10 秒。难怪你需要 2GB 来运行一个糟糕的 servlet 容器,而这个容器曾经运行在 128MB 中。并且不要让我开始记录异常堆栈跟踪的成本......

    【讨论】:

    • 我在这里读到了 Gold.. 不错。
    【解决方案2】:

    理论上,如果你使用 AOP 做你可以用硬耦合做的事情,那么没有性能问题,没有开销,也没有额外的方法调用,除非你什么都不做。 AOP 框架为您提供了一种方法来消除硬耦合并分解您的横切关注点。

    在实践中,AOP Framework 可以引入 3 种类型的开销:

    • 开火时间
    • 拦截机制
    • 消费者整合(提出建议的方式)

    更多详情可以参考when-is-aop-code-executed

    请注意如何实现建议,因为横向代码是装箱/拆箱和反射的诱惑(在性能方面很昂贵)。

    如果没有 AOP 框架(硬耦合您的横切关注点),您可以更轻松地开发假设的建议(专用于每种处理),而无需装箱/拆箱和反射。

    您必须知道,大多数 AOP 框架不提供完全避免装箱/拆箱和反射的方法。

    我开发了一个来应对大部分缺失的需求,集中在 3 件事上:

    • 用户友好(轻量级、易学)
    • 透明(不包含破坏代码)
    • 高效(无装箱/拆箱、名义用户代码中无反射以及良好的拦截机制)

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

    【讨论】:

      【解决方案3】:

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

      起初,我们认为不会有性能问题,但我们没有考虑到我们调用数据库数千次的方程式。 aop 中的一个方面调用不会对性能产生太大影响,但将其乘以数千倍,事实证明,由于这些额外的方法调用,新系统比旧系统更差。

      我会说 aop 是一个很好用的系统,但请注意有多少方法调用被添加到您的应用程序中

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          你有没有想过一个 AOP 工具可以在需要时在运行时向对象添加方面? .net 有一个“使用动态装饰器向对象添加方面”(http://www.codeproject.com/KB/architecture/aspectddecorator.aspx)。我相信你可以为 Java 写一个类似的。

          【讨论】:

            【解决方案6】:

            如果要考虑性能,我们使用AspectJ 效果很好。

            因为它使用字节码编织(编译时间与运行时差别很大),所以它是目前最快的 AOP 框架之一。见:AOP Benchmarks

            【讨论】:

            • 存档版依然可用here
            【解决方案7】:

            只要您控制您的 AOP,我认为它是有效的。无论如何,我们确实遇到了性能问题,所以根据自己的推理,我们并没有完全控制;)这主要是因为任何编写方面的人都完全了解所有其他,这一点很重要> 系统中的各个方面以及它们如何相互关联。如果你开始做“聪明”的事情,你可以瞬间超越自己。在一个大型项目中做一些聪明的事情,很多人只能看到系统的一小部分,这在性能方面可能是非常危险的。这个建议可能在没有 AOP 的情况下也适用,但是 AOP 可以让您以一些真正优雅的方式自爆。

            Spring 还使用代理来进行范围操作,那是一个很容易导致不希望的性能损失的领域。

            但鉴于你有控制权,AOP 唯一真正的痛点是对调试的影响。

            【讨论】:

              【解决方案8】:

              如果您使用的是基于代理的 AOP,那么您所说的每个应用方面都会有 1 个额外的 Java 方法调用。那里的性能影响可以忽略不计。唯一真正关心的是代理的创建,但这通常只在应用程序启动时发生一次。 SpringSource 博客对此有一篇很棒的文章:

              http://blog.springsource.com/2007/07/19/debunking-myths-proxies-impact-performance/

              【讨论】:

              • 真的吗?为什么调试时在堆栈跟踪中看到这么多方法调用(~5)?
              • 你能发布堆栈跟踪吗?我可能不正确,忘记了反射 API 中有一些额外的调用,以便代理调用目标。您使用的是 JDK 还是 CGLIB 代理?
              • @LiorH 这取决于应用的方面的数量。如果有多个通知,则可能有多个方法调用。 This 图表可以帮助理解这种情况。
              • 博客链接非常有用!感谢分享。
              • 我看到每个 AOP 包装调用在堆栈中大约有 5 个方法调用,这些调用在 Java 反射 Method.invoke() 调用中终止。我认为这也许就是 Cliff 所指的。无论如何,如果这 5 次调用的成本在 500ns(纳米)左右,那么对于交易等基本项目就不用担心了。对于大多数应用程序来说,每个 HTTP 请求都可以使用少量代理。
              【解决方案9】:

              当我使用它时,我没有 - 但是我的应用程序不是你的应用程序。

              如果您将它用于在非常紧凑的循环中使用的调用,则机会会显着影响性能。如果它只是用于每个请求检查一次安全性并缓存各种内容,我看不出它有多重要 - 但这就是为什么您应该对 您的应用程序进行分析和基准测试。

              我意识到“用你的应用衡量”可能不是你想要的答案,但它很可能是你猜到的答案:)

              【讨论】:

              • 确实可以。在争论为什么不需要进行基准测试时,我希望我可以链接到这篇文章。 :-)
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-07-10
              • 1970-01-01
              • 1970-01-01
              • 2012-12-10
              • 2010-09-26
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多