I would offer +0.3 of a vote to now plan to call the next release 3.0 as a result of this.
On Fri, Mar 4, 2011 at 3:58 PM, Daniel Kulp <[email protected]> wrote: > > > > On Friday 04 March 2011 3:47:55 PM Daniel Kulp wrote: >> 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.... >> </bean> >> >> 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. >> >> Dan >> >> 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 > [email protected] > http://dankulp.com/blog > Talend - http://www.talend.com >
