Archive

Archive for the ‘Java’ Category

Some Post JavaOne Fun

June 6th, 2009 jlee Comments off

It’s friday night.  Finally back at the hotel without a meeting or party or a session to go to.  What else is there to do but port benchmarks of debatable value to my favorite new non-Java language:  Fan.  Earlier in the I was directed to this blog post detailing some performance problems with groovy.  Yes, I know the blog is old.  That’s not the point I want to make here.  This week at Javaone, there was a presentation doing some more performance comparisons between languages on the JVM.  This one caught my eye because it’s the first one I’ve seen in the wild that included Fan.  So this got me thinking about year old post and the ray tracing exercise.  How would fan hold up?  I decided to find out.  Because there’s no better way to spend a Friday night after long conference week, right?

The Fan code isn’t idiomatic (I’m not that bored tonight).  It’s just a quick and dirty port from the Java source to Fan.  For reference, I reran the Java version and then the Fan version.  This test is running on OS X and Java 1.6u13.  Without further hand waving, here’s the results:

time java -cp . ray 8 512
 
real	0m14.210s
user	0m12.443s
sys	0m1.313s
 
time fan tracer::RayTest 8 512 
 
real	0m17.700s
user	0m15.832s
sys	0m0.672s

As you can see, the performance is really quite good. I’ll probably play with the source over the next few days and see if I can’t improve it a bit. The fan code is pretty rough so there’s probably a fair bit to be done to speed that up a bit.  I’ll attach the source so if anyone else is interested the source will be available.  I have to say, though, that’s not too shabby at all.

Technorati Tags: ,

Categories: Java, fan

String Concatenation Revisited

February 23rd, 2009 jlee 4 comments
This entry is part 5 of 5 in the series Tips

I had intended to do some follow up numbers to my previous post but I got a bit sidetracked by work and the like.  My simple tests all work with one String that’s created then thrown away.  This test helped me resolve the question I had when I started down that road but stops short of a more general answer.  Then I saw this pingback which led me here.  There’s some nice analysis and insights to consider.  So given the shortcomings of my little benchmark and the comments there, I wanted to expand my test a bit and see what things look like when the loop doesn’t throw away the data.  The test is simple enough again:

import java.util.*;
import java.text.*;
 
public class ConcatenationTest {
	private static long concat(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = "Loop " + x + " of " + count + " iterations.";
		}
		return System.currentTimeMillis() - start;
	}
 
	private static long append(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = new StringBuilder("Loop ")
				.append(x)
				.append(" of ")
				.append(count)
				.append("iterations.")
				.toString();
		}
		return System.currentTimeMillis() - start;
	}
 
	private static long concatAcrossLoops(int count) {
		long start = System.currentTimeMillis();
		String s = "";
		for(int x = 0; x < count; x++) {
			s += "Loop " + x + " of " + count + " iterations.";
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("concatAcrossLoops time = " + time);
		return time;
	}
 
	private static long appendAcrossLoops(int count) {
		long start = System.currentTimeMillis();
		StringBuilder s = new StringBuilder();
		for(int x = 0; x < count; x++) {
			s.append("\nLoop ")
				.append(x)
				.append(" of ")
				.append(count)
				.append("iterations.");
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("appendAcrossLoops time = " + time);
		return time;
	}
 
	public static void main(String[] args) {
		int count = 10000;
		List concats = new ArrayList();
		List appends = new ArrayList();
		List concatsAcross = new ArrayList();
		List appendsAcross = new ArrayList();
		for(int x = 0; x < 10; x++) {
			concats.add(concat(count));
			appends.add(append(count));
			concatsAcross.add(concatAcrossLoops(count));
			appendsAcross.add(appendAcrossLoops(count));
		}
 
		String header = "concats   appends   concats across loops   appends across loops";
		String format = "%7d %9d %22d %22d\n";
		System.out.println(header);
		for(int x = 0; x < 10; x++) {
			System.out.printf(format, concats.get(x), appends.get(x), concatsAcross.get(x), appendsAcross.get(x));
		}
	}
}

And then the results:

concats appends concats across loops appends across loops
48 14 18990 1276
27 11 14581 1442
4 4 13206 1253
3 3 13478 1438
4 4 12651 1444
4 3 12485 1403
4 3 12608 1318
4 3 13152 1312
3 4 12535 1390
4 3 12444 1329

Notice after the first two loops the numbers for all runs drops. As the JIT compiler kicks in, we get some optimization but as you can see concatenation across loop iterations is incredibly much more expensive. In this case, StringBuilder is still the clear winner.

update
There was a typo in the original test. I was calling toString() in the appendsAcrossLoop test which was entirely unnecessary. (I forgot to remove that call when adapting from the earlier iteration.) The new results are below. I included them here rather than just replacing the table above as it shows just how expensive that toString() is.

concats appends concats across loops appends across loops
42 15 16562 4
5 8 12564 5
4 3 11601 2
4 2 11141 2
4 3 11025 3
3 3 11260 3
3 3 11062 3
3 3 11738 2
4 2 11078 2
4 2 11130 3

Technorati Tags: , ,

Categories: Java

Isn’t it time for GCJ to die?

February 9th, 2009 jlee 1 comment

What’s the motivation for gcj these days?  Originally, everyone wanted a GPLd JVM so gcj kinda made sense.  At least in spirit.  It’s never been a functional equivalent for an actual JVM, though.  I’ve seen nothing but problems with it for years in IRC channels.  It’s partial implementation of the spec has led to endless confusion for uncounted newbies coming to the java channel for help.  It doesn’t help that the ideologues at Debian, et. al, continue to package gcj as if it were java.  Well, we have a  GPLd JVM now.  Everything about it is open source (or just about done…).

GCJ, as I see it, serves no more useful purpose than allowing those in charge of it to hold on to some ideal (or maybe pride).  I know this is inflammatory for a good number of people, but why persist?  Is it the native compilation you like?  The slow, misbegotten catastrophe that it is?  It’s slower than running java bytecode and seems to eliminate several key features of Java (like dynamic classloading).  Even before Sun GPLd their (our?  I’m a Sun guy after all…) JVM, gcj adoption was miniscule at best.  So, what’s the point?  Can’t we move on from gcj?  Or at a minimum, stop packaging it as the default JVM when it’s not actually a java implementation?  That’d work for me.  I’m just tired of seeing newbies getting tripped up by some distro’s ideological navel gazing.

Technorati Tags: , , ,

Categories: Java

Changing the Current Directory

February 5th, 2009 jlee 2 comments
This entry is part 3 of 5 in the series Tips

One of the more common requests I see online from beginners (and from a not-so-beginner just now) is how to change the current directory.  This one is really simple, so here’s a quick snippet and the output.

System.out.println(new File(“.”).getAbsolutePath());
System.setProperty(“user.dir”, System.getProperty(“java.io.tmpdir”));
System.out.println(new File(“.”).getAbsolutePath());

And the output:

/Users/jlee/.
/tmp/.

See?  Simple.

Technorati Tags: , ,

Categories: Java

String Concatenation Options

January 29th, 2009 jlee 5 comments
This entry is part 4 of 5 in the series Tips

There’s a new inspection in IDEA 8 (might just be in the EAP at this point) that will convert string concatentation to a variety of different approaches.  One of these options is to use String.format().  I started applying this option to some code I’m working because it’s certainly more readable than some of the concatenation stuff I’d been doing.  But I started thinking that I should probably profile this before I get too crazy with it just to make sure I’m not hamstringing myself with this.  So I wrote a simple test to see what the fastest option was and I was a little surprised by the results.

First, let’s see the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.text.*;
 
public class test {
	private static long concat(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = "Loop " + x + " of " + count + " iterations.";
		}
		return System.currentTimeMillis() - start;
	}
 
	private static long format(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = String.format("Loop %s of %s iterations."
				, x, count);
		}
		return System.currentTimeMillis() - start;
	}
 
	private static long format2(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = MessageFormat.format("Loop {0} of {1} iterations."
				, x, count);
		}
		return System.currentTimeMillis() - start;
	}
 
	private static long append(int count) {
		long start = System.currentTimeMillis();
		for(int x = 0; x < count; x++) {
			String s = new StringBuilder("Loop ")
				.append(x)
				.append(" of ")
				.append(count)
				.append("iterations.")
				.toString();
		}
		return System.currentTimeMillis() - start;
	}
 
	public static void main(String[] args) {
		int count = 1000000;
 
		for(int x = 0; x < 10; x++) {
			System.out.println("concat = " + concat(count));
			System.out.println("String.format = " + format(count));
			System.out.println("MessageFormat.format = " + format2(count));
			System.out.println("append = " + append(count));
			System.out.println();
		}
	}
}

This admittedly naive “benchmark” runs through four options and prints out the basic timing results.  I’ve compiled the results below in a table:

concat String.format MessageFormat.format append
408 3164 9099 376
338 2876 8559 340
300 3013 8655 398
342 2938 8511 311
308 2911 8570 310
306 2924 8726 320
316 3019 9006 414
306 2994 8673 331
346 3022 9588 311
312 2988 8590 313

As you can see both format methods take considerably more time than the other two.  I was a little surprised to see this though the magnitude of the difference was more surprising than than the difference itself.  So neither of those are options you’ll want to consider in areas that get called often.  The one that was really suprising for me was the relative similarity between concatenating strings and appending using StringBuilder.  While StringBuilder was generally faster than string concats, the difference was rather minimal and in some runs actually slower.  What this says to me is that the generally accepted “wisdom” that String concatenation is slower than using StringBuilder is clearly wrong.

On the other, I’m not really a performance expert so I might be doing something stupid here or missing something fundamental.  The test seems rather straightforward, though.  What do you think?

Technorati Tags: , ,

Categories: Java