2012-11-21 18 views
8

Ich schreibe eine Java EE 6-Webanwendung, und ich bemerke eine erhebliche Leistungseinbußen bei der Verwendung eines injizierten Objekts im Gegensatz zu dem Erstellen und Verwenden des Objekts direkt. Der Overhead scheint in der Größenordnung von 50 bis 60 ms pro Methodenaufruf zu liegen.Leistungseinfluss der Verwendung von CDI

Zum Beispiel dauert die Verwendung nicht injizierter 150-Methodenaufrufe ca. 500 ms, während die Verwendung der Methodenaufrufe mit injizierten Objekten 150.000 - 13.000 ms benötigt. Eine Größenordnung Unterschied und dann einige.

Ist das normal?

Ich bin auf JBoss AS 7.1.1 Finale ausgeführt, die Weld verwendet, um CDI zu behandeln.

Das injizierte Objekt wird als Singleton-Bean definiert (über die Annotation javax.ejb.Singleton). Könnte dies einen Teil des Problems verursachen? Oder ist es nur der Weld-Proxy, der die Verlangsamung verursacht?

+0

Wenn Sie über die Leistung kümmern, die viel, du bist * * Art und Weise verschraubt von Java EE mit zu beginnen. Ich bezweifle ernsthaft, dass proxied Interceptors der Flaschenhals in Ihrem Code sein werden. Das heißt, was ich tun würde, einen Haltepunkt im Debugger innerhalb des abgefangenen Methodenaufruf gesetzt wird zu sehen, wie viele Schichten von Proxies es passieren hat - es ist möglich, dass Sie einige Konfigurationsproblem haben, die eine übermäßige Menge von ihnen verursacht werden angewendet . – millimoose

+0

Durch die Änderung des injizierten Objekts als ApplicationScoped anstelle von @Singleton wurden die Dinge um eine Größenordnung beschleunigt. Ich habe keine Ahnung warum und wäre daran interessiert, wenn irgendjemand etwas dazu sagen würde. – Troup

+0

Das ist ... seltsam.Ich würde immer noch im Debugger herumstochern, um zu sehen, was der Unterschied in den Aufrufketten ist. Sonst müssen wir die Ursache für ein vages Symptom erraten. Im Allgemeinen glaube ich, dass die Ursache für diesen Overhead * AOP sein sollte, aber es ist mehr als alles andere. – millimoose

Antwort

9

Nach etwas Hilfe von dem hervorragenden Weld Forum habe ich entdeckt, dass:

ist standardmäßig Singleton Session Beans Transaktions (Abschnitt 13.3.7 der EJB 3.1-Spezifikation) und erfordern Erwerb einer exklusiven Sperre für jeden Aufruf der Geschäftsmethode (Abschnitte 4.8.5.4 und 4.8.5.5). Im Gegensatz dazu ist javax.inject.Singleton nicht transaktional und unterstützt keine durch Container gesteuerte Nebenläufigkeit (die wichtigste Konsequenz ist, dass vom Container kein Sperrschema implementiert wird).

Wenn Sie Ihre Singleton Session-Bean mit @TransactionAttribute (NOT_SUPPORTED) und @Lock (READ) mit Anmerkungen versehen, sollten Sie deutlich bessere Leistung finden, obwohl es noch einige Kopf sein kann. Wenn Sie keine EJB-Funktionen benötigen, bleiben @ApplicationScoped (javax.inject.Singleton nicht durch CDI definiert ist, und seine Semantik sind daher nicht von dieser Spezifikation geregelt).

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

Leider auch nach war immer noch sehr schlecht meine EJB Singletons mit @TransactionAttribute (NOT_SUPPORTED) und @Lock (READ) die Leistung mit Anmerkungen versehen (siehe Timings von Original-Beitrag).

So Die Botschaft ist Bohnen Session EJB Singleton injiziert nicht, wenn Sie absolut haben und selbst dann der Performance-Overhead darüber im Klaren sein, die anfallen dürften. Für Methoden, die selten aufgerufen werden, könnte es vernachlässigbar sein, aber wie in unserem Fall akkumulieren sich kleine Gemeinkosten schnell, wenn es sich um eine stark genutzte Methode handelt.

Wir brauchen nicht die EJB-Funktionen und ApplicationScoped Einschalten sah Größenordnung Verbesserungen in der Leistung der spezifischen Methode, die auf das injizierte Bohne durch.