2012-11-21 17 views
8

Sto scrivendo un'applicazione web Java EE 6 e noto un impatto significativo sulle prestazioni quando si utilizza un oggetto iniettato rispetto alla creazione e all'utilizzo diretto dell'oggetto. L'overhead sembra essere dell'ordine di 50 - 60 ms per chiamata di metodo.Impatto delle prestazioni dell'utilizzo di CDI

Ad esempio, l'utilizzo di 150 chiamate di metodo non iniettate richiede circa 500ms mentre l'oggetto iniettato utilizza 150 chiamate di metodo da 12.000 a 13.000 ms. Una differenza di ordine di grandezza e poi alcuni.

È normale?

Sono in esecuzione su JBoss AS 7.1.1 final che utilizza Weld per gestire CDI.

L'oggetto inserito è definito come un bean singleton (tramite l'annotazione javax.ejb.Singleton). Questo potrebbe causare parte del problema? O è solo il proxy di saldatura a causare il rallentamento?

+0

Se ti interessa così tanto le prestazioni, sei * * * avvitato usando Java EE per cominciare. Dubito seriamente che gli intercettori proxy saranno il collo di bottiglia del codice. Detto questo, ciò che farei è inserire un punto di interruzione nel debugger all'interno della chiamata al metodo intercettato per vedere quanti livelli di proxy deve passare: è possibile che si verifichi un problema di configurazione che causa l'applicazione di una quantità eccessiva di tali proxy . – millimoose

+0

La modifica dell'oggetto iniettato da ApplicationScoped anziché @Singleton ha accelerato le cose di un ordine di grandezza. Non ho idea del perché e sarei interessato se qualcuno avesse qualche feedback su questo. – Troup

+0

Questo è ... strano.Continuerò a sondarlo nel debugger per vedere qual è la differenza nelle catene di chiamata. Altrimenti siamo bloccati a indovinare la causa di un sintomo vago. In generale, credo che la causa di questo sovraccarico si veda * dovrebbe * essere AOP, ma è una supposizione più che altro. – millimoose

risposta

9

Dopo qualche aiuto da parte l'eccellente Weld forum ho scoperto che:

Per impostazione predefinita, i session bean singleton sono transazionale (sezione 13.3.7 della specifica EJB 3.1) e richiedono l'acquisizione di un esclusivo blocco per ogni chiamata del metodo di business (sezioni 4.8.5.4 e 4.8.5.5). Al contrario, un javax.inject.Singleton non è transazionale e non supporta la concorrenza gestita dal contenitore (la principale conseguenza di è che nessuno schema di blocco è implementato dal contenitore ).

Se annotare il bean di sessione Singleton con @TransactionAttribute (NOT_SUPPORTED) e @Lock (READ), si dovrebbe vedere prestazioni significativamente migliori, anche se ci può essere ancora un po 'di testa. Se non hai bisogno di funzionalità EJB, continua con @ApplicationScoped (javax.inject.Singleton non è definito da CDI, e la sua semantica non è quindi governata da tale specifica).

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

Purtroppo, anche dopo l'annotazione mia EJB Singleton con @TransactionAttribute (NOT_SUPPORTED) e @Lock (READ) la performance era ancora molto povero (vedi tempi di post originale).

Quindi il messaggio take home non viene iniettato bean di sessione EJB Singleton a meno che non sia assolutamente necessario e anche in tal caso essere consapevoli del sovraccarico delle prestazioni che è probabile che si verifichi. Per i metodi che vengono raramente invocati potrebbe essere trascurabile, ma come nel nostro caso le piccole spese generali si accumulano rapidamente se si tratta di un metodo molto utilizzato.

Non avevamo bisogno delle funzioni EJB e al passaggio a ApplicationScoped abbiamo visto miglioramenti nell'ordine di grandezza delle prestazioni del metodo specifico che ha richiamato il bean iniettato.