Home » Profiling Java Efficiency

Share This Post

Featured Tutorials / Tutorial

Profiling Java Efficiency

Profiling without an  IDE with Java

Think you need an IDE or a paid IDE to profile? Think again. I explain in this post how to do this with the basic Java language. You will find some interesting results in the very simple test case that I made up for this article. Later I will try to come back and upgrade this article to test a couple of other methods mentioned and other types of objects.

How to use Java to determine the size of something.

How to Get the Size of an Object in Java is an article that talks about using getObjectSize(Object objectToSize) of Instrumentation interface It seems this interface was created to work with bytecode but it can be used to get an estimated object size. In his article he states.

Minimum object size is 16 bytes for modern 64-bit JDK since the object has 12-byte header, padded to a multiple of 8 bytes. In 32-bit JDK, the overhead is 8 bytes, padded to a multiple of 4 bytes.

I had already stated in on article how Java References use 4 bytes with 32-bit JVM and 8 bytes with 64-Bit JVM.

https://github.com/DimitrisAndreou/memory-measurer Is a tool some guy wrote to help measure object size.

SizeOf() for Java And in this article, the guy says the sizes I list below may be specific to the particular JVM implementation. So if you check the size of something and get results you do not expect that could be the problem. Below I reiterate the sizes of various Java Primitives.

  • The bit (on or off, 0 or 1, true or false)
    • boolean actually its stored as around 1 byte in the JVM, but its JVM dependent.
    • BitSet is a class that stores and handles bits in bit size memory allocations.
  • The Byte (8 bits)
    • byte  1 byte signed whole -128 to 127  byte times 0xff will convert it to 0 to 255
    • short 2 bytes signed whole -32,768 to 32,767
    • int     4 bytes signed whole -2,147,483,648 to 2,147,483
    • long  8 bytes signed whole -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
    • float  4 bytes signed real 6-7 significant digits  ±3.40282347E+38F
    • double 8 bytes signed real 15 significant digits  ±1.79769313486231570E+308
  • Character
    • char 2 bytes  whole unsigned 0 to 65535  (for unicode characters) ASCII still fits in first 256 or 0 to 255 space.
    • String  a most common object that holds any number of char’s.
  • Reference
    • reference 4 bytes on 32 bit JVM, 8 bytes on 64 bit JVM so 8 bytes for most of us.

A crude method is to use the code below to get the size in Kilobytes. What we would do is make some object. Create a bunch them, say 1000. But first, we get the memory our app is currently using. Then make the objects. Then get the memory our app is now using. We then subtract the first from the second. And dividing that by in this case 1000 should give us an approximation. What is interesting about the results after running the code below is why the first two are 0? But according to this a java.lang.Integer object uses about 30 bytes.

This is because used memory shows what has been allocated for use for your app code and data. It’s allocated in chunks of memory for a memory heap. So you have to play with his method until you get a somewhat acceptable approximation.  Integer actually uses 32 Bytes if you manually calculate the data size. Java Tip 130: Do you know your data size? is another interesting article written around 2002. It says Integer uses 16 bytes, but this is probably on a 32 bit JVM not a 64 Bit JVM. It also mentions using Runtime.gc() to clean up the heap when trying to find the size of something as we have below.

  • 1000 gets 0
  • 10,000 gets 0
  • 100,000 gets 33
  • 1,000,000 gets 29

Object SizeOf() Estimator

Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() / 1024
import java.util.*;

public class Profiling {
 private void log(String s){
  System.out.println(s);	 
 }
 int numberObjects = 10000;
 ArrayList theObjects = new ArrayList();
 public int getRandomInt(int max, int min){
  return (int)((Math.random() * ((max - min) + 1)) + min);
 }
 public long getKiloBytesUsed(){
 	return (long)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() / 1024);
 }
 public long getBytesUsed(){
 	 return (long)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
 }
 void pause(){
  try {
    Thread.sleep(2000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }	 
 }
 long startUsed = 0;
 long endUsed = 0;
 
 public Profiling(){
  startUsed=getBytesUsed();
  log("start bytes:"+startUsed);
  makeListOfInts();
  endUsed=getBytesUsed();
  log("end bytes:"+endUsed);
  long usedTotal = endUsed-startUsed;
  long used = usedTotal/numberObjects;
  log(""+numberObjects+" Integers used approx. "+(usedTotal)+"bytes ram");
  log("So this would be "+used+"bytes for each Integer object.");
 }
 
 public void makeListOfInts(){ 	 
  for(int i=0;i<numberObjects;i++){
   theObjects.add(new Integer(getRandomInt(50,100)));
  }
 }
 public static void main(String args[]){
  new Profiling();
 }
}

How to use Java to determine execution time of something.

In this next example, we use currentTimeMillis() method to do a similar feat. We want to time the making of the Integers and the Sorting of the Integers. All we must do is get the System time in milliseconds just before an operation and just after and subtract. I obtained these results which reveal something amazing. 10x the number of objects slows 77 times for make and to 20 times for sort operations.

  • 1,000,000 Integers
    • Make 85ms
    • Sort 264ms
  • 10,000,000 Integers
    • Make 6.551s
    • Sort  5.202s

Operation  Execution Time Estimator

System.currentTimeMillis()

import java.util.*;

public class Profiling {
 private void log(String s){
  System.out.println(s);	 
 }
 int numberObjects = 10000000;
 ArrayList theObjects = new ArrayList();
 public int getRandomInt(int max, int min){
  return (int)((Math.random() * ((max - min) + 1)) + min);
 }
 public long getKiloBytesUsed(){
 	return (long)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() / 1024);
 }
 public long getBytesUsed(){
 	 return (long)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
 }
 public long getTime(){
  return System.currentTimeMillis();	 
 }
 void pause(){
  try {
    Thread.sleep(2000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }	 
 }
 long startTime = 0;
 long endTime = 0;
 
 public Profiling(){
  
  startTime=getTime();
  makeListOfInts();
  endTime=getTime();
  long timeSecs = (endTime-startTime);
  log("Time to make Integers is "+timeSecs+" milliseconds");
  
  startTime=getTime();
  sort();
  endTime=getTime();
  timeSecs = (endTime-startTime);
  log("Time to sort Integers is "+timeSecs+" milliseconds");
  
 }
 
 public void makeListOfInts(){ 	 
  for(int i=0;i<numberObjects;i++){
   theObjects.add(new Integer(getRandomInt(50,100)));
  }
 }
 public void sort(){
 	 Collections.sort(theObjects);
 }
 public static void main(String args[]){
  new Profiling();
 }
}

Finally

So as you can see you do not need a fancy IDE to do some profiling. Just remember when measuring memory usage you can’t not be creating objects other than the ones you want size. In other words, you might not be able to use this method within a larger application that has threads running or is otherwise doing other things. Instead, you will have to make a special case test just to measure one object. However, using the time measuring tool should work fine in most cases. In some cases, you may have to do the same and build a special test case. For example, again, I’m not totally sure but there could be other background threads or something going on that might slow what you’re doing down.

When start projects or applications efficiency is usually the last concern. It’s when you get closer to a final product and the application becomes large that you have issues. So…

Make it…

  • work
  • right
  • fast/small
  • cheap

Share This Post

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>