Showing posts with label new. Show all posts
Showing posts with label new. Show all posts

Friday, 24 June 2011

new vs newInstance() performace

Everybody knows (or should) that any operation performed using reflections is bound to be slower than its static, compiled counterpart. But as jdk versions are increasing, this time is decreasing.

I was making the classic micro-benchmarking error of not warming up the VM, so here’s the slightly modified version of the code:

public class TheCostOfReflection {

public static void main(String[] args) throws Exception {
int nObjects = 100;
Object[] objects = new Object[nObjects];

// warm up a bit
int warmupLoops = Math.min(nObjects, 100);
for (int i = 0; i < warmupLoops; i++) {
testNewOperator(nObjects, objects);
testNewInstance(nObjects, objects);
}

System.gc();

// using new
System.out.println("Testing 'new'...");
long newTime = testNewOperator(nObjects, objects);
System.out.println("Took " + (newTime / 1000000f) + "ms to create " +
nObjects + " objects via 'new' (" +
(nObjects / (newTime / 1000000f)) +
" objects per ms)");
System.gc();
// using newInstance() on class
System.out.println("Testing 'newInstance()'...");
long niTime = testNewInstance(nObjects, objects);
System.out.println("Took " + (niTime / 1000000f) + "ms to create " +
nObjects + " objects via reflections (" +
(nObjects / (niTime / 1000000f)) +
" objects per ms)");
// ratio
System.out.println("'new' is " + (niTime / (float) newTime) +
" times faster than 'newInstance()'.");
}

private static long testNewInstance(int nObjects, Object[] objects)
throws Exception {
long start = System.nanoTime();
for (int i = 0; i < nObjects; i++) {
objects[i] = Object.class.newInstance();
}
return System.nanoTime() - start;
}

private static long testNewOperator(int nObjects, Object[] objects) {
long start = System.nanoTime();
for (int i = 0; i < nObjects; i++) {
objects[i] = new Object();
}
return System.nanoTime() - start;
}
}

Running this with -Xms512m -Xmx512m* yields the following result:

Testing 'new'...
Took 7.610116ms to create 1000000 objects via 'new' (131404.05 objects per ms)
Testing 'newInstance()'...
Took 184.72641ms to create 1000000 objects via reflections (5413.41 objects per ms)
'new' is 24.273798 times faster than 'newInstance()'.

Nearly 25x slower. If you lower the value of nObjects the difference gets smaller, though.
Testing 'new'...
Took 0.002794ms to create 100 objects via 'new' (35790.98 objects per ms)
Testing 'newInstance()'...
Took 0.021581ms to create 100 objects via reflections (4633.7056 objects per ms)
'new' is 7.7240515 times faster than 'newInstance()'.

Adding a -server flag to the VM parameters did the trick, though.
Testing 'new'...
Took 8.862299ms to create 1000000 objects via 'new' (112837.54 objects per ms)
Testing 'newInstance()'...
Took 13.91287ms to create 1000000 objects via reflections (71875.88 objects per ms)
'new' is 1.5698942 times faster than 'newInstance()'.

And for 100 object instantiations:
Testing 'new'...
Took 0.002864ms to create 100 objects via 'new' (34916.20 objects per ms)
Testing 'newInstance()'...
Took 0.006007ms to create 100 objects via reflections (16647.24 objects per ms)
'new' is 2.0974162 times faster than 'newInstance()'.

When the JIT magic kicks in, you get some SERIOUS improvements.
* NOTE: 512m to avoid garbage collection interference. You can run with -XX:+PrintGCDetails to ensure that the GC isn’t acting during the instantiation loops. You should see two full GC passages though, because of lines 14 and 23.
I did run the tests a dozen times for each test; the outputs posted fall within the averages.
Tip of the day: Even though I got far better results after introducing the warmup phase, I still suggest you use the good ol’ Factory pattern. Unless you’re creating a few dozen instances in a non-critical zones of your code, the factory is the way to go, as newInstance() can never (?) get as fast as new.


Friday, 22 April 2011

Object Creation and Destruction

To create an object of a particular class use the new operator. For example, now that there is a constructor for the Box class you can make specific instances or discrete copies of a box by using the assignment operator and the new memory allocation operator as in:
Box box_1=new Box(3,4,5);
Note: Once a class has been specified, a datatype exists with the same name.
You do not need to destroy or remove an object when it is no longer needed. Java automatically flags unused objects and applies garbage collection when appropriate. However you may occasionally need to use the finalize() method to insure that a non-Java resource such as a file handle or a window font character is released first. The general form is:
void finalize()
{
//cleanup code goes here
super.finalize() //parent too!
}