9

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

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

这是平常的吗?

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

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

4

1 回答 1

10

在优秀的 Weld 论坛的帮助下,我发现:

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

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

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

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

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

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

于 2012-11-22T08:53:02.130 回答