Sorry for the cross posting, but I thought that you people would appreciate this as well...;-) -jon ---------- From: Stefano Mazzocchi <[EMAIL PROTECTED]> To: _ Java Apache <[EMAIL PROTECTED]> Subject: Still making 1.0b4-dev faster... Date: Fri, Apr 9, 1999, 7:48 AM Hi, I went on profiling the JServConnection class and I totally rewrote the readHexData() and readData() methods that were shown to be major hotspots in the code. My final results are incredible! What was wrong -------------- The AJP1.1 protocol was designed with simplicity in mind and for that reason it was based on text protocols like HTTP. For this reason, the server side must perform some parsing on the incoming stream to be able to create the needed strings out of such AJP requests. The problem was the abuse of String and StringBuffer objects, as well as a very poor knowledge of how GC works. This is reflected from the old days of 9.0 and it's been around since there (Ed indipendently came out with the same ideas for 0.9.12. Too bad I noted we were doing the same things after I was done changing it :-(. What I did ---------- 1) optimized the HEX to decimal translation with a lookup table insted of java.lang.Character methods. I tried to avoid to touch internal byte to char translations and such because of the Unicode overhead we do not care since mod_jserv doesn't even know about it. 2) used an adaptive byte[] buffer (just one per JServConnection!) instead of creating a new String for every line. This alone saves almost _half_ of the memory created by JServConnection. 3) implemented a clean-room C-like implementation of StringBuffer specifically tuned for our AJP needs. Another big memory save since no object must be created 4) removed all of the if (xxx == null) methods and change them to Exception catching (which is both more elegant and faster) 5) inlined the call to readHexLine() to avoid passing parameters around (as you see from the code, it doesn't hurt readability that much since it integrates very well with the parsing loop. Results ------- I profiled JServ by running it with the two different JServConnection versions and hitting it with JMeter at 5 threads, 300 ms delay for a total of around 50 hits (57 for new, 54 for old). JServ was run by the IBM JInsight instrumented JVM. The first thing that stroke me was the side of the trace file: new code trace file size = 5280kb (92,6 kb/request) old code trace file size = 8400kb (155 kb/request) the new code generated 40% less traces! The total number of clock ticks counted for the execution of all the JServConnection objects indicates the time spent on the execution of the servlet (both logging and class autoreloading was disabled, compiled with TURBO mode on) new JServConnection total time = 8187707 ticks (143644 ticks/request) old JServConnection total time = 11556202 ticks (214004 ticks/request) the new code is 33% faster!!!! If you used to load balance with three machines, you can now use two and dedicate the third to your coffee pot ;-) If we take into account the memory savings (that reflects on GC being called less frequently) we see how much we gain from this little hack ;-) BTW, keep in mind that YMMV! (numbers in real life welcome!) Stefano Mazzocchi A language that doesn't affect the way you think about programming, is not worth knowing. <[EMAIL PROTECTED]> Alan J. Perlis --------------------------------------------------------------------- ------------------------------------------------------------ To subscribe: [EMAIL PROTECTED] To unsubscribe: [EMAIL PROTECTED] Archives and Other: <http://java.apache.org/main/mail.html/> Problems?: [EMAIL PROTECTED] ---------------------------------------------------------------- To subscribe: [EMAIL PROTECTED] To unsubscribe: [EMAIL PROTECTED] Archives and Other: <http://java.apache.org/main/mail.html/> Problems?: [EMAIL PROTECTED]