Hi,
my attention has been recently brought to a scenario in which an Apache CXF client invokes an endpoint operation in a loop and the number of invocations performed in a given amount of time (say, 2 minutes) is used as benchmark for measuring WS stack performances. It's actually a very simplistic scenario, with a plain JAX-WS single thread client sending and receiving small RPC/Lit SOAP messages [1]. The reason why I've been asked to have a look is that with default settings the Apache CXF JAX-WS impl seems to perform *shamefully* bad compared to the Metro (JAX-WS RI) implementation. I've been blaming the user log configuration, etc but when I eventually tried on my own I could actually reproduce the bad results. I've been profiling a bit and found few hot spot area where CXF could possibly be optimized, but the big issue really seems to be at the HTTPCounduit / HTTPURLConnection level. I found that almost all the invocations end up into sun.net.www.http.HttpClient.New(..) calling available() method [2] as part of the process for re-using cached connections [3]; that goes to the wire to try reading and takes a lot of time. When the RI does the equivalent operation, the available() method is not called [4], resulting in much better performances. By looking at the JDK code, it looks to me that the problem boils down to sun.net.www.protocol.http.HttpURLConnection#streaming() [5] returning different values, as a consequence of the fixedContentLenght attribute being set to a value different from -1 when running on CXF only. As a matter of fact, that is set when HTTPConduit.WrappedOutputStream#thresholdNotReached() is called, whenever a message is completely written to the outpustream buffer before the chunking threshold is reached (at least AFAIU). I've searched through the JAX-WS RI and could not find any place where setFixedLengthStreamingMode is called on the connection instead. So, I've performed two quick and dirty tries: the first time I forced allowChunking = false on the client policy, the second time I commented out the code in HTTPConduit.WrappedOutputStream#thresholdNotReached(). In both cases I managed to get performances comparable to what I can get with the JAX-WS RI.
Now, few questions:
- are we really required to call setFixedLengthStreamingMode as we currently do? what's the drawback of not calling it? - should we actually do something for getting decent performances by default in this scenario? (not sure expecting the user to disable chunking is that an option...) As a side note, the relevant part of the JDK HttpClient code changed between JDK6 and JDK7, so things have not always been as explained above...

Cheers
Alessio


[1] http://www.fpaste.org/176166/14223765/
[2] http://pasteboard.co/FR5QVrP.png
[3] http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/http/HttpClient.java#276
[4] http://pasteboard.co/FR8okYM.png
[5] http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/protocol/http/HttpURLConnection.java#HttpURLConnection.streaming%28%29

--
Alessio Soldano
Web Service Lead, JBoss

Reply via email to