Chatted with Alessio about this on IRC. It looks like a bug in the JDK introduced in Java7 update 40. A bug was logged:
https://bugs.openjdk.java.net/browse/JDK-8044726 but then closed a non-reproducible. Alessio will look into seeing if that can be re-opened. Meanwhile we’ll likely remove the call to setFixedLengthStreamingMode. That will result in an extra byte[] copy of the message, but this is only for smaller messages (hasn’t hit the threshold yet) and thus is fairly quick and is certainly MUCH MUCH faster than the problems we’re seeing with the call to setFixedLengthStreamingMode(). Dan > On Jan 27, 2015, at 12:14 PM, Alessio Soldano <[email protected]> wrote: > > 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 > -- Daniel Kulp [email protected] - http://dankulp.com/blog Talend Community Coder - http://coders.talend.com
