Monday, April 07, 2008

Primitives vs Objects

At times we come across a situation when we need to decide whether to use primitive types or wrapper objects for numeric values in Java. The wrapper classes come in handy when we need to pass on the null values, which can't be achieved with primitive types as they are always initialized to their respective default values.

The general concept is that primitive types are far more efficient then using wrapper classes in terms of memory usage and time taken for creating the data types. For one of my project I need to decide which one to use, so I thought about measuring the cost difference between these two options. I wrote a simple class which creates n number of objects of a class either having primitives or wrapper classes. The code is given below-

import java.util.ArrayList;
import java.util.List;

public class ObjectVsPrimitive {

List<WrapperNumbers> wrappers;
List<PrimitiveNumbers> primitives;

public void testWrapper(int count) {
wrappers = new ArrayList<WrapperNumbers>();
for (int i = 0; i <= count; i++)
wrappers.add(new WrapperNumbers());
}

public void testPrimitive(int count) {
primitives = new ArrayList<PrimitiveNumbers>();
for (int i = 0; i <= count; i++)
primitives.add(new PrimitiveNumbers());
}

public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: java ObjectVsPrimitive 'P' (or 'O') <some number>");
System.exit(-1);
}

int count = 0;

try {
count = Integer.parseInt(args[1]);
} catch (NumberFormatException e) {
System.out.println("Please enter a valid number.");
System.exit(-1);
}

ObjectVsPrimitive test = new ObjectVsPrimitive();
StopWatch watch = new StopWatch();

if (args[0].equalsIgnoreCase("p"))
test.testPrimitive(count);
else
test.testWrapper(count);

watch.stop();
double freeMem = Runtime.getRuntime().freeMemory() / 1024 / 1024;
double totalMem = Runtime.getRuntime().totalMemory() / 1024 / 1024;
System.out.println("Time taken: " + watch.time() + " seconds");
System.out.println("Total Memory: " + totalMem + "MB, Free Memory: " + freeMem + " MB"
+ ", Used Memory: " + (totalMem - freeMem) + "MB");
}

/**
* A class having primitives for holding numeric values.
*/
@SuppressWarnings("unused")
public class PrimitiveNumbers {
private short SHORT = 10;
private int INT = 10;
private long LONG = 10l;
private double DOUBLE = 10.0d;
private float FLOAT = 10.0f;
}

/**
* A class having wrapper classes for holding numeric values.
*/
@SuppressWarnings("unused")
public class WrapperNumbers {
private Short SHORT = new Short((short) 10);
private Integer INT = new Integer(10);
private Long LONG = new Long(10l);
private Float FLOAT = new Float(10.0f);
private Double DOUBLE = new Double(10.0d);
}

/**
* Simple class to measure time.
*/
static class StopWatch {
private long start;
private long stop;

public StopWatch() {
start();
}

/** Starts timer */
public final void start() {
this.start = System.currentTimeMillis();
this.stop = 0;
}

/** Stops timer */
public void stop() {
this.stop = System.currentTimeMillis();
}

/** Returns time taken in seconds */
public double time() {
return (stop - start) / 1000.0;
}
}
}
A test run for creating 1 million objects of the class having primitives consumed 52MB of RAM while class having wrappers consumed a whooping 111MB, which is more then twice over the primitives.

Memory (MB)

Creation of 1 million objects of the class having primitives took 0.77 seconds while class having wrappers took 2.64 seconds, which is around 3.5 times over the primitives.

Time (seconds)

If one looks at the comparative results and calculates it in percentage terms then obviously choice will be primitives. If we think deeply then using wrappers may make sense, if there is a requirement. Think does your application will ever need 1 million objects in memory at the same time or do you need to create 1 million objects within couple of seconds only? If this is not the case then use the wrappers without worrying much about the performance cost.

2 Comments: