More tests

Following my tests a couple of days ago and the ensuing discussion, I have done some further testing to better understand what the HotSpot optimiser in the Sun Java VM can do.

In particular, I made an interface called CollectionInterface which my TestCollection class adheres to, and made the test program use that instead of the class type. This means that HotSpot does not have enough static type information to inline method calls on the TestCollection class (or whatever it was doing with them), and so the manually factored loop is significantly faster than the normal one.

Here is my test program now:

public class ManualMethod {
public static void main(String[] args) {
TestCollection list = new TestCollection(1000000000);

long normalTime = test(list);
long normalTime2 = test(list);
long normalTime3 = test(list);
long factoredTime = testFactored(list);
long factoredTime2 = testFactored(list);
long factoredTime3 = testFactored(list);

System.out.println("Normal: " + normalTime + " ms");
System.out.println("Normal: " + normalTime2 + " ms");
System.out.println("Normal: " + normalTime3 + " ms");
System.out.println("Factored: " + factoredTime + " ms");
System.out.println("Factored: " + factoredTime2 + " ms");
System.out.println("Factored: " + factoredTime3 + " ms");
System.out.println("Side effects: " + list.sideEffects);

private static long test(CollectionInterface list) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); ++i) {
return System.currentTimeMillis() - startTime;

private static long testFactored(CollectionInterface list) {
int length = list.size();
long startTime = System.currentTimeMillis();
for (int i = 0; i < length; ++i) {
return System.currentTimeMillis() - startTime;

And the output:

$ java ManualMethod
Normal: 2192 ms
Normal: 2182 ms
Normal: 2204 ms
Factored: 737 ms
Factored: 727 ms
Factored: 885 ms
Side effects: 0

With the server VM, the effect is now even more pronounced:

$ java -server ManualMethod
Normal: 1458 ms
Normal: 1451 ms
Normal: 1445 ms
Factored: 1 ms
Factored: 0 ms
Factored: 0 ms
Side effects: 0

Presumable here the server VM can completely remove the loop in the factored case as it is not producing any useful results, but it cannot know whether the call to CollectionInterface.size() will have side effects so cannot remove the loop in the case that calls that on every iteration.

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: