Performance Zone is brought to you in partnership with:

Ronald Daniel is a software developer, specializing in J2EE Programming technologies and frameworks. Has been in the IT World since 2008, still much to learn yet. Been a trainer for a while, specializing in training subjects: Java, J2EE, Sql-ing in Oracle, Sql Server and MySQL. Has been involved in numerous IT Software Development Projects and still wants to be better than yesterday. Feel free to drop email to rd.djunaedi@gmail.com Ronald is a DZone MVB and is not an employee of DZone and has posted 5 posts at DZone. You can read more from them at their website. View Full User Profile

Variable Declaration: Member, Outside or Inside Loop

03.25.2013
| 1921 views |
  • submit to reddit

 Well, my colleague and I, were having this discussion before. He was a bit confused with best practice (in performance matter) to declare the variable, whether it’s as a member, inside loop or outside loop.

public class InsideLoop {
    public void test() {
 
        for (int i = 0; i < 100000; i++) {
            int calc = (int) (i * Math.pow(i, i * 2));
            System.out.println(i);
        }
 
    }
 
    public static void main(String []args) {
        long startMem = Runtime.getRuntime().freeMemory();
        long startTime = System.currentTimeMillis();
        new InsideLoop().test();
        long endTime = System.currentTimeMillis();
        long endMem = Runtime.getRuntime().freeMemory();
        System.out.println("Inside Loop Memory taken: " + (startMem - endMem)+ " bytes");
        System.out.println("Inside Loop Time taken: "+ (endTime-startTime) +" ms");
    }
 
}
public class OutsideLoop {
    public void test() {
        int calc = 0;
        for (int i = 0; i < 100000; i++) {
            calc = (int) (i * Math.pow(i, i * 2));
 
        }
 
    }
 
    public static void main(String[] args) {
        long startMem = Runtime.getRuntime().freeMemory();
        long startTime = System.currentTimeMillis();
        new OutsideLoop().test();
        long endTime = System.currentTimeMillis();
        long endMem = Runtime.getRuntime().freeMemory();
        System.out.println("Outside Loop Memory taken: " + (startMem - endMem)+ " bytes");
        System.out.println("Outside Loop Time taken: " + (endTime - startTime) + " ms");
    }
 
}
public class Member {
    int calc;
 
    public void test() {
 
        for (int i = 0; i < 100000; i++) {
            calc = (int) (i * Math.pow(i, i * 2));
            System.out.println(i);
        }
 
    }
 
    public static void main(String[] args) {
        long startMem = Runtime.getRuntime().freeMemory();
        long startTime = System.currentTimeMillis();
        new Member().test();
        long endTime = System.currentTimeMillis();
        long endMem = Runtime.getRuntime().freeMemory();
        System.out.println("Member Memory taken: " + (startMem - endMem)+ " bytes");
        System.out.println("Member Time taken: " + (endTime - startTime) + " ms");
    }
 
}

And the results are:

Inside Loop Memory taken: 16044520 bytes
Inside Loop Time taken: 626 ms

Outside Loop Memory taken: 16044264 bytes
Outside Loop Time taken: 638 ms

Member Memory taken: 16044392 bytes
Member Time taken: 610 ms

As we can see, there is no significant difference with where did you place the variable – at least for this test cases. Thanks for the magic of JIT feature that Java has on it, so the optimization can be done at the runtime of the application and made this achieved.

Of course, this cant be taken generally, especially for non-primitive data type, String, Thread, etc. And depends of what operations that you do for that Object.



Published at DZone with permission of Ronald Daniel, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Eugene Ciurana replied on Mon, 2013/03/25 - 12:13pm

 Hola.

Not a lot of JIT magic there.  If you dump the .class file to JVM bytecodes, you will see that the compiler sets the space to be allocated when the method first enters scope, regardless of where in the method the variable was declared.

Outside:

<code>

public class Test {
  public static void main(java.lang.String...) throws java.lang.Exception;
  Code:
  0: iconst_0   
  1: istore_2   
  2: iload_2   
  3: bipush  10
  5: if_icmpge  28
  8: iload_2   
  9: i2d   
  10: iload_2   
  11: i2d   
  12: iconst_2   
  13: iload_2   
  14: imul   
  15: i2d   
  16: invokestatic  #2  // Method java/lang/Math.pow:(DD)D
  19: dmul   
  20: d2i   
  21: istore_1   
  22: iinc  2, 1
  25: goto  2
  28: return   
}

</code>

Inside:

<code>

public class Test {
  public static void main(java.lang.String...) throws java.lang.Exception;
  Code:
  0: iconst_0   
  1: istore_1   
  2: iload_1   
  3: bipush  10
  5: if_icmpge  28
  8: iload_1   
  9: i2d   
  10: iload_1   
  11: i2d   
  12: iconst_2   
  13: iload_1   
  14: imul   
  15: i2d   
  16: invokestatic  #2  // Method java/lang/Math.pow:(DD)D
  19: dmul   
  20: d2i   
  21: istore_2   
  22: iinc  1, 1
  25: goto  2
  28: return   
}

</code>

A better practice for new programmers, though, might be to remind them to not allocate/release resource-intensive objects in a loop.  I was surprised to recently see some very slow code from experienced guys who did just that.

Anyway -- check your own code's behavior with:

<code>

javap -c YourClassFileHere.class

</code>

Cheers!

pr3d

Ronald Daniel replied on Mon, 2013/03/25 - 12:35pm in response to: Eugene Ciurana

Hi, Many thanks for the input. If this possible, may i see the actual code of the allocation/releasing object that you talked about?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.