cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Kulp <>
Subject Re: Startup speed, XML, etc.....
Date Fri, 04 Mar 2011 20:47:55 GMT

I just committed the gigantic refactoring of the Spring bus stuff to base it 
on the  ExtensionManagerBus.   I'll describe it in a minute, but first the 
performanc result on my test case:

Running test - 2.4.0-SNAPSHOT
Setup: 29105 51/sec
Invoke: 38174 39/sec
Setup config: 39026 38/sec

Compared to the 2.3.3:
> Running test - 2.3.3
> Setup: 49732 30/sec
> Invoke: 62276 24/sec
> Setup config: 56164 26/sec

As you can see, it's quite a bit faster across the board now.   That's great.  
The code is also (IMO) a LOT simpler now.   We no longer have to modify both 
bus-extension.xml and cxf-extension-blah.xml files.    The extension loading 
is more unified.  The extension retrieval from the Bus is simpler and, for the 
most part, identical between the Spring and Non-Spring cases.    And the 
performance rocks.  :-)

For the most part, it's simple to modify existing applications to work.   Just 
remove all the imports for everything except META-INF/cxf/cxf.xml  and META-
INF/cxf/cxf-servlet.xml if you use a servlet.   However, there are a couple of 
other "gotchas" that I encountered:

1) We had several files that did something like:

<bean id="cxf" class=".... CXFBusImpl>
     ... conifure some interceptors....

That no longer works.   The proper way to do that has been to use the 
<cxf:bus> namespaced object.  It's been that way for a while.  Creating 
separate Bus's like that is just asking for having things become confused.     
I converted all the tests to do that properly.   You COULD potentially change 
that to:
<bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus">
but using cxf:bus is definitely the better way to go.   Directly instantiating 
and depending on internal "impl" classes and such is generally a bad idea.

2)  depends-on and injections - since almost none of the CXF internal beans 
are now defined in the Spring context, you cannot really depend on them 
directly.   That's not a normal thing anyway.     The Bus is really the only 
thing that is in the context.   

In anycase, the rest was fairly simple.   If you do define beans in the spring 
config, they will override/replace the auto loaded stuff (just like before), 
the configurations stuff remains the same, etc....    It just starts up a ton 
faster and uses a bit less memory.    :-)

I definitely have some more testing to do, but I think it's a good start.


On Thursday 03 March 2011 5:01:58 PM Daniel Kulp wrote:
> 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

Daniel Kulp
Talend -

View raw message