2012-11-21 101 views
8

我正在编写一个Java EE 6 Web应用程序,并且我注意到在使用注入对象与直接创建和使用对象时显着的性能影响。开销似乎是每个方法调用50-60毫秒的量级。使用CDI对性能的影响

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

这是平常的吗?

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

注入的对象被定义为单例bean(通过javax.ejb.Singleton注释)。这是否会造成问题的一部分?或者它只是Weld代理导致减速?

+0

如果您关心的是性能,那么您就开始使用Java EE进行操作。我严重怀疑代理拦截器会成为你的代码中的瓶颈。也就是说,我要做的是在拦截方法调用中的调试器中放置一个断点,以查看它必须经过多少层代理 - 可能会导致某些配置问题导致应用过量的代理。 – millimoose

+0

将注入的对象更改为ApplicationScoped而不是@Singleton将事物加速了一个数量级。我不知道为什么,如果有人对此有任何反馈,我会感兴趣。 – Troup

+0

这很奇怪。我仍然在调试器中捅了一下,看看调用链有什么不同。否则,我们坚持猜测一个模糊症状的原因。一般来说,我认为你所看到的这种开销的原因应该是AOP,但这是一个猜测。 – millimoose

回答

9

从优秀焊接论坛一些帮助后,我发现:

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

如果注释与 @TransactionAttribute(NOT_SUPPORTED)和@Lock(READ)的单会话bean,你应该看到 显著更好的性能,但仍可能存在一些 开销。如果您不需要EJB功能,请使用 @ApplicationScoped(javax.inject.Singleton不由CDI定义,因此它的语义不受该规范的支配)。

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

可悲的是连我的注释EJB单用@TransactionAttribute(NOT_SUPPORTED)和@Lock(READ)后的表现仍然很差(请参阅从原来的职位计时)。

因此,回家的消息是不注入EJB Singleton会话bean,除非您绝对必须,甚至然后意识到可能发生的性能开销。对于很少被调用的方法,它可能可以忽略不计,但在我们的情况下,如果它是一种常用方法,那么小的开销会迅速累积。

我们不需要EJB特性,并且切换到ApplicationScoped时,通过注入的bean调用的特定方法的性能有所改善。