【问题标题】:Performance impact of using CDI使用 CDI 的性能影响
【发布时间】:2012-11-21 16:00:09
【问题描述】:

我正在编写一个 Java EE 6 Web 应用程序,我注意到使用注入对象与直接创建和使用对象相比,性能会受到显着影响。每个方法调用的开销似乎约为 50 - 60 毫秒。

例如,使用非注入的 150 次方法调用大约需要 500 毫秒,而使用注入的对象 150 次方法调用需要 12,000 - 13,000 毫秒。一个数量级的差异,然后是一些。

这是平常的事吗?

我在 JBoss AS 7.1.1 final 上运行,它使用 Weld 来处理 CDI。

注入的对象被定义为一个单例 bean(通过 javax.ejb.Singleton 注释)。这可能是问题的一部分吗?还是只是 Weld 代理导致速度变慢?

【问题讨论】:

  • 如果您那么在意性能,那么您方式会被一开始就使用 Java EE 搞砸了。我严重怀疑代理拦截器将成为您代码中的瓶颈。也就是说,我要做的是在被拦截的方法调用内的调试器中放置一个断点,以查看它必须通过多少层代理——可能你有一些配置问题导致应用过多的代理.
  • 将注入的对象更改为 ApplicationScoped 而不是 @Singleton 加快了一个数量级的速度。我不知道为什么,如果有人对此有任何反馈,我会很感兴趣。
  • 您是否尝试过使用分析器来追踪消耗时间的地方?
  • javax.inject 中的 Singleton 非常没有价值。如果您需要 EJB 的所有功能,请使用 EJB 之一,否则使用 j.e.c 之一。另外,是的,Weld 和 OWB 使用代理。 AS 7.1.1 使用 Weld 1.1.5,我相信 1.1.9,也许它是 1.18,虽然它已经过时并且包括一些额外的性能改进。至于 Spring perf,Mark Struberg 发现 CDI(在 Weld 和 OWB 中)更快。
  • 是的,你说得对。很抱歉造成混乱。

标签: java java-ee-6 jboss7.x cdi jboss-weld


【解决方案1】:

从优秀的 Weld 论坛获得一些帮助后,我发现:

默认情况下,单例会话 bean 是事务性的(第 13.3.7 节 的 EJB 3.1 规范),并要求获得一个独占的 锁定每个业务方法调用(第 4.8.5.4 节和 4.8.5.5)。相比之下,javax.inject.Singleton 不是事务性的,也不支持容器管理的并发(主要 结果是没有锁定方案是由 容器)。

如果你用注解你的单例会话 bean @TransactionAttribute(NOT_SUPPORTED) 和 @Lock(READ),你应该看到 明显更好的性能,尽管可能仍有一些 高架。如果您不需要 EJB 功能,请坚持使用 @ApplicationScoped(CDI 未定义 javax.inject.Singleton,并且 因此,它的语义不受该规范的约束)。

https://community.jboss.org/thread/213684?tstart=0

遗憾的是,即使在使用 @TransactionAttribute(NOT_SUPPORTED) 和 @Lock(READ) 注释我的 EJB 单例之后,性能仍然很差(请参阅原始帖子中的时间安排)。

因此,带回家的信息是不要注入 EJB 单例会话 bean,除非您绝对必须这样做,甚至要意识到可能产生的性能开销。对于很少被调用的方法,它可以忽略不计,但在我们的例子中,如果它是一个频繁使用的方​​法,那么小开销会迅速累积。

我们不需要 EJB 功能,并且在切换到 ApplicationScoped 后,调用注入 bean 的特定方法的性能得到了数量级的改进。

【讨论】:

    猜你喜欢
    • 2010-09-30
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多