email@hidden wrote:
>... the second call took less time than the first.
>
>My question is whether this behavior is:
>a) a StringBuffer problem solely, or
>b) related to any intesive usage of String objects, or
>c) a version specific JVM problem, and/or
>d) a Mac JVM implementation problem, or
>e) something else entirely.
e.
If the second call is faster, then the difference is most likely a
consequence of JIT compiling taking effect. It may even take effect at
some point during the first invocation, in which case the time it takes for
the JITC to compile from byte-code to native-code is being attributed to
the first invocation. That would skew the results even more against the
first invocation.
To find out more about JIT compilation, see:
<http://en.wikipedia.org/wiki/Just-in-time_compilation>
To eliminate JITC as a factor, use one of these 'java' invocations:
java -Xint ...rest of args...
java -Xcomp ...rest of args...
To see what these are doing, read the output of:
java -X
which does describe -Xint but not its polar opposite -Xcomp, with -Xmixed
lying between the two opposites.
> for (int i = 0; i<n.length; i++) {
> sb.append("\t" + n[i] + "\n");
> }
Every time you use the + operator to concatenate Strings with other values,
the compiler translates it into the creation of an ephemeral StringBuffer,
a series of append() calls on that StringBuffer, then a call to toString().
In JDK 1.5+, a StringBuilder is used instead, which at least cuts
synchronization costs, but still has all the object creation costs.
So at each iteration, this code is creating a temporary StringBuffer,
appending a tab, then a String representing the double's value, then a
newline. It's then converting that StringBuffer to a String and appending
it to sb. Furthermore, the String representing the double's value is
created using another temporary StringBuffer.
If you want to use StringBuffer efficiently, you should use only the
append() methods that take non-String primitive types, and ONLY use the
String-appending method with literal Strings. For example:
sb.append( "\t" );
sb.append( n[i ] ); // calls append(double)
sb.append( "\n" );
There may be even more efficient ways to use StringBuffer, but the loop you
have now is probably one of the least efficient ways, because of the large
number of ephemeral objects being created and discarded.
However, none of this matters in your benchmark, because the measured times
are not accounting for the possibility of JITC kicking in at an
indeterminate time and place. And presumably GC isn't kicking in, either,
otherwise the second call would probably be slower than the first.
By the way, the speed difference between a series of print()'s vs. building
lines in a StringBuffer first is of little consequence, UNLESS the
underlying OutputStream is unbuffered. As long as the OutputStream is
buffered at a reasonable size (say 16 KB or so), then the overall time will
probably be dominated by the I/O speed when the buffer fills up and gets
written out.
In other words, even if the times for print() or a StringBuffer could be
reduced to exactly zero (infinitely fast), you would still have a
speed-limit from writing to disk. It might be 5 MB/sec or 100 MB/sec
depending on the media, the bus it's on, etc., but it's still going to be
the dominant factor in overall throughput for a given medium.
-- GG
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden
This email sent to email@hidden