I've done quite a bit of work now on trunk to speed up the "normal" use cases.
With what's on trunk now, a normal JAX-WS client that doesn't include any
spring config will get the extension bus instead. With my lastest set of
changes, a default extension bus now starts up without ANY XML parsing and
very few beans and such created. This is MUCH faster now. I wrote a
little benchmark based on the java-first-jaxws example (to avoid any WSDL
related things) and depending on cxf-bundle to make sure we get EVERYTHING and
then does:
public static void doIteration(boolean invoke) {
BusFactory.setThreadDefaultBus(null);
BusFactory.setDefaultBus(null);
Service service = Service.create(SERVICE_NAME);
String endpointAddress = "http://localhost:9000/helloWorld";
service.addPort(PORT_NAME,
SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
if (invoke) {
service.getPort(HelloWorld.class).sayHi("Hello");
} else {
service.getPort(HelloWorld.class);
}
}
in a loop under 3 conditions:
1) First is with invoke=false to basically time all the upfront setup costs.
That includes creating the Bus, creating the Service, and then creating the
Proxy.
2) Then with invoke=true to include the additional stuff of creating the
interceptor chains and conduits and doing a real invoke.
3) Again with invoke=false, but this time with specifying a spring config file
(cxf.xml). This basically is the same as (1), but involves the spring Bus
now.
I then ran this with several versions of CXF. Results are below. (first
number is the # of ms for 1500 iterations, then it's iterations/sec)
Basically, the Extension bus stuff is now a TON faster. For 80% of the use
cases, it's much faster. I'm definitely excited about that. The spring
case slowed down a bit. I'm not sure why. I'll need to profile that a bit
to figure it out. In anycase, for standalone applications and cases where
config is done through API's, this is quite a bit faster. As we start
thinking about Blueprint and such, this can be important. Right now, the
server side parts are all very spring based and thus won't benefit from this.
:-(
One thing I'm going to try next is making META-INF/cxf/cxf.xml just have a
single bean (the ExtensionBus) and removing all the cxf-extension-*.xml files
(except for the HTTP things, more in a sec on that) and seeing what happens.
The HTTP stuff on the server side becomes a "challenge". Right now, we have
basically 3 implementations of the HTTPDestinationFactory: jetty, servlet,
and OSGi. The user pretty much selects the one they want by importing the
appropriate cxf-extension file and not the others in their spring config.
While it works, there is a down side: you can only have one implementation
in you application. Normally not a problem, but there IS the use case of a
Servlet based application that may also want a service or two exposed on a
specific jetty port (like maybe for a decoupled client) that isn't under the
servlet containers control.
My proposal for that would be to put a single HTTPDestinationFactory in the
http module that would hold onto a DestinationRegistry. The OSGi and Servlet
based things would just grab that DestinationRegistry for their dispatching.
However, when the HTTPDestinationFactory is asked to create a destination for
a "full" URL (like "http://localhost:8080/blah") instead of a path (like
"/blah"), it would call on a delegate that the Jetty stuff would provide to
it. I need to think about this a bit more, but I think it would work fairly
well.
Dan
Running test - 2.4.0-SNAPSHOT
Setup: 29086 51/sec
Invoke: 42558 35/sec
Setup config: 69839 21/sec
Running test - 2.3.3
Setup: 49732 30/sec
Invoke: 62276 24/sec
Setup config: 56164 26/sec
Running test - 2.3.0
Setup: 44233 33/sec
Invoke: 56496 26/sec
Setup config: 55305 27/sec
Running test - 2.2.12
Setup: 48193 31/sec
Invoke: 55737 26/sec
Setup config: 50582 29/sec
Running test - 2.1.9
Setup: 43944 34/sec
Invoke: 47652 31/sec
Setup config: 44550 33/sec
Running test - 2.1.1
Setup: 47335 31/sec
Invoke: 48871 30/sec
Setup config: 49255 30/sec