-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Xie,
On 3/3/2010 11:54 AM, Xie Xiaodong wrote: > I think log.debug() method should first check current logging levels, or our > code will have those if() {} template everywhere. [snip] > For log.debug() part, seems I misunderstood your meaning. Sorry about that, > you are right. But I do not think it matters too much. :) Well, if were using tricks to avoid synchronization, we probably ought to avoid four object creations (StringBuilder, char[] in sb, String, and char[] in s) plus the character-copy operations. This is a filter that is supposed to avoid performance impact on the webapp: this is such a cheap optimization, it would be foolish not to do it. > Java 6 hotspot can determine that the StringBuffer synchronization isn't > actually used across threads in many cases, and thus it doesn't bother > synchronizing. Thus, the performance of the two classes becomes identical. > > http://www.javalobby.org/java/forums/t88518.html It's a rough reference from a comment on a blog. Gimmie something I can really read, not "I remember a guy saying once..". Jeremy Manson says this: " A final note. Some people think that there is no performance impact to using StringBuffer instead of StringBuilder, because of all of the clever things JVMs do to eliminate synchronization (I can blog about this, too, if you want). This is a little unclear. Whether it can even perform these optimizing transformations definitely depends wildly on which JDK you use; I wrote a microbenchmark to test it, and the results differed on different JDKs -- but all that microbenchmarks really demonstrate is the performance of the microbenchmark. " (http://jeremymanson.blogspot.com/2008/08/dont-use-stringbuffer.html from 24 August 2008) > But it is more secure to not depend on specific jvm version, so it is more > appropriate to use StringBuilder when necessary. I agree. Using my own microbenchmark (below), these are the results I get: (On my OpenVZ dev box, Linux 2.6 kernel) $ java -showversion BufferVsBuilder 10000000 java version "1.6.0_12" Java(TM) SE Runtime Environment (build 1.6.0_12-b04) Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode) Priming... Running............... Builder: 24538 Buffer: 25745 Overhead: 1657 $ java -showversion BufferVsBuilder 10000000 java version "1.6.0_12" Java(TM) SE Runtime Environment (build 1.6.0_12-b04) Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode) Priming... Running............... Builder: 24175 Buffer: 25416 Overhead: 1656 (On my laptop, W7 32-bit) F:\Users\Chris\Desktop>java -showversion BufferVsBuilder 10000000 java version "1.6.0_18" Java(TM) SE Runtime Environment (build 1.6.0_18-b07) Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing) Priming... Running............... Builder: 27507 Buffer: 31525 Overhead: 1183 F:\Users\Chris\Desktop>java -showversion BufferVsBuilder 10000000 java version "1.6.0_18" Java(TM) SE Runtime Environment (build 1.6.0_18-b07) Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing) Priming... Running............... Builder: 27339 Buffer: 31346 Overhead: 1116 It seems that, in these two environments, StringBuilder outperforms StringBuffer by a small margin (5% on average in my Linux environment, 13% in my Microsoft Windows environment), but consistently. It seems that the JVM has to do some work to even determine if the synchronization can be eliminated before it can actually do it, so why bother making it do that work in the first place? Avoiding synchronization is simply the right choice. - -chris The code: public class BufferVsBuilder { static long elapsedBuilder = 0; static long elapsedBuffer = 0; static long elapsedNothing = 0; public static void testBuilder(long iterations) { long elapsed = System.currentTimeMillis(); for(long i=iterations; i>0; --i) { StringBuilder sb = new StringBuilder(128); sb.append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") ; } elapsed = System.currentTimeMillis() - elapsed; elapsedBuilder += elapsed; } public static void testBuffer(long iterations) { long elapsed = System.currentTimeMillis(); for(long i=iterations; i>0; --i) { StringBuffer sb = new StringBuffer(128); sb.append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") .append("some text") ; } elapsed = System.currentTimeMillis() - elapsed; elapsedBuffer += elapsed; } public static void testNothing(long iterations) { long elapsed = System.currentTimeMillis(); for(long i=iterations; i>0; --i) { StringBuffer sb = new StringBuffer(128); } elapsed = System.currentTimeMillis() - elapsed; elapsedNothing += elapsed; } public static void main(String[] args) { long iterations = Long.parseLong(args[0]); System.out.println("Priming..."); System.out.flush(); // Allow the JIT to work it's magic testBuilder(iterations); testBuffer(iterations); // Re-set counters and start the real tests elapsedBuilder = 0; elapsedBuffer = 0; System.out.print("Running..."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testBuilder(iterations); System.out.print("."); System.out.flush(); testBuffer(iterations); System.out.print("."); System.out.flush(); testNothing(iterations); System.out.println(); System.out.println("Builder: " + elapsedBuilder); System.out.println("Buffer: " + elapsedBuffer); System.out.println("Overhead: " + elapsedNothing); } } -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkuOrj0ACgkQ9CaO5/Lv0PCAbgCeLkbndgo1VsC/M+e2dGfVy3Fl 4dMAoKCHnBRwZvayRdSPXibVxFI7Hes3 =k26e -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org