2012-11-21 102 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調用的特定方法的性能有所改善。