>> I read in many websites than StringBuilder offers better performance
>> than StringBuffer. So, in my code, I changed all StringBuffer usages to
[quoted text clipped - 13 lines]
> below: For 1024 iterations, I got the same result you did, i.e.
> StringBuffer gave better performance:
The actual performance is going to be very dependent on the operation
mix. A variation of your program suggests that some of the effects may
be due to outside influences such as page faulting or cache missing. I
modified the program to do each test multiple times, alternating:
StringBuffer: 3255575 ns
StringBuilder: 6224512 ns
StringBuffer: 3741265 ns
StringBuilder: 2922576 ns
StringBuffer: 296705 ns
StringBuilder: 229733 ns
StringBuffer: 186285 ns
StringBuilder: 148315 ns
StringBuffer: 1421934 ns
StringBuilder: 149066 ns
StringBuffer: 181475 ns
StringBuilder: 145825 ns
StringBuffer: 192282 ns
StringBuilder: 143341 ns
StringBuffer: 185336 ns
StringBuilder: 151989 ns
The first two lines look as though StringBuffer is faster than
StringBuilder, but the later lines suggest the opposite. I assume this
behavior is unrelated to the real program issue.
Here's my version of the program:
public class StringBufferPerformance {
static final int numIterations = 1024;
public static void main(String[] args){
StringBuffer sbuf =
new StringBuffer("same text as the other guy");
StringBuilder sbld =
new StringBuilder("same text as the other guy");
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
timeBuffer(sbuf);
timeBuilder(sbld);
}
/**
* @param sbld
*/
private static void timeBuilder(StringBuilder sbld) {
long t;
t = System.nanoTime();
for(int i = 0; i < numIterations; ++i) {
sbld.append("a");
sbld.deleteCharAt(0);
}
t = System.nanoTime() - t;
System.out.println("StringBuilder:\t" + t + " ns");
}
/**
* @param sbuf
*/
private static void timeBuffer(StringBuffer sbuf) {
long t = System.nanoTime();
for(int i = 0; i < numIterations; ++i) {
sbuf.append("a");
sbuf.deleteCharAt(0);
}
t = System.nanoTime() - t;
System.out.println("StringBuffer:\t" + t + " ns");
}
}
Jeffrey Schwab - 24 Aug 2006 16:21 GMT
>>> I read in many websites than StringBuilder offers better performance
>>> than StringBuffer. So, in my code, I changed all StringBuffer usages to
[quoted text clipped - 39 lines]
> StringBuilder, but the later lines suggest the opposite. I assume this
> behavior is unrelated to the real program issue.
That makes sense. String modification is so pervasive in actual
programs... It's hard to come up with test cases that mimic the Wild.
Thomas Hawtin - 24 Aug 2006 19:35 GMT
> The first two lines look as though StringBuffer is faster than
> StringBuilder, but the later lines suggest the opposite. I assume this
> behavior is unrelated to the real program issue.
There is a lot of work going on behind the scenes to load your program
even before it starts off on the first iteration. Most of the Java
library is still using StringBuffer. Therefore, it seems likely that the
StringBuffer code is mostly compiled while the StringBuilder starts off
interpreted.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/
Arne Vajhøj - 25 Aug 2006 04:34 GMT
> The actual performance is going to be very dependent on the operation
> mix.
I have a StringBuffer test program that do a mix of append and
substring combined with some String operations.
StringBuffer results says 1.11 while StringBuilder
results say 1.18 on 32 bit Win32 SUN Java 1.5.
(code attached in StringBuilder incarnation below for the curious)
That is a 6% difference.
I am not surprised that the difference is not bigger.
The synchronized overhead has become smaller in newer
JVM's.
And the code do other things than just StringB*
operations. But so do real world applications.
Arne
===================================================
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.util.Random;
public class JvmTest {
private final static int REP = 10;
private final static int NSTR = 100;
private final static int N = 1000000;
private final static String ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static NumberFormat nf = new DecimalFormat("0.00");
private static Random rng = new Random();
private static int scale;
private static void printres(long t1, long t2, int n1, int n2,
String ops) {
double xperf = (double)n1 * (double)n2 / ((t2 - t1) / 1000.0) ;
String sperf= nf.format(xperf/1000000);
System.out.println(sperf + " million " + ops + " per second");
}
public static void teststr() {
int nstrscale = NSTR / scale;
long t1 = System.currentTimeMillis();
for(int i = 0; i < nstrscale; i++) {
StringBuilder sb = new StringBuilder("");
for(int j = 0; j < N; j = j + 10) {
String s = ALFA + ALFA;
int ix = (i + j) % ALFA.length();
sb.append(s.substring(ix, ix + 1) + s.substring(ix + 1,
ix + 3) + s.substring(ix + 3, ix + 6) + s.substring(ix + 6, ix + 10));
}
int ix = rng.nextInt(N);
if(sb.length() != N || sb.charAt(ix) != ALFA.charAt((i +
ix) % ALFA.length())) {
System.out.println("String test error");
System.exit(0);
}
}
long t2 = System.currentTimeMillis();
printres(t1, t2, nstrscale, N / 10, "string operations");
}
public static void main(String[] args) {
System.out.println(System.getProperty("java.vm.vendor") + " " +
System.getProperty("java.vm.name") + " " +
System.getProperty("java.vm.version"));
if(args.length > 0) {
scale = Integer.parseInt(args[0]);
} else {
scale = 1;
}
for(int i = 0; i < REP; i++) {
teststr();
}
}
}