2

I was watching a video on basic Java game programming and saw this bit of code

private void render() {
    BufferStrategy bs = getBufferStrategy();
    if (bs == null){
        createBufferStrategy(3);
        return;
    }
}

It seems to me like the code would run faster by declaring the reference "bs" outside of the render method so it isn't recreated every single frame, but then I actually tested it myself and found the opposite was true.

package test;

public class tm {
    static String s;

    public static void loop1(){
        s = "hi";
    }

    public static void loop2(){
        String d;
        d = "hi";
    }
    public static void main(String[] args) {

        long x1 = System.nanoTime();
        for(int i = 0;i<100000;i++)
            loop1();
        long x2 = System.nanoTime();
        for(int i = 0;i<100000;i++)
            loop2();
        long x3 = System.nanoTime();

        System.out.println(x2-x1);
        System.out.println(x3-x2);
    }
}

After running this a few times it became apparent that loop1 took on average an order of magnitude longer. It seems counter intuitive that simply accessing an instance field takes longer than creating a new variable. Am I missing something or is it that simple? How can I learn which equivalent actions take longer so I can better optimize my code?

1937701
284818

2036061
599144

3189017
675694

1971058
608125

there are a few runs. Did I benchmark incorrectly?

pyjamas
  • 4,608
  • 5
  • 38
  • 70
  • What's the actual output? – Anubian Noob Sep 04 '15 at 17:42
  • 1937701 284818 2036061 599144 3189017 675694 1971058 608125 there are a few runs Oh it doesn't format right in comments, I'll add to the OP – pyjamas Sep 04 '15 at 17:44
  • 2
    Try running `loop2` *before* `loop1`. What do you see then? – sstan Sep 04 '15 at 17:46
  • 1
    Oh it didn't change! I guess I don't understand benchmarking correctly. I'm confused now. I'll read that link – pyjamas Sep 04 '15 at 17:47
  • 1
    @sstan Not a duplicate of that. That question is necassary reading though. – Anubian Noob Sep 04 '15 at 17:48
  • 1
    @Anubian: Which part of this question is not answered by doing a proper benchmark? – sstan Sep 04 '15 at 17:53
  • A lot of the answers and tips in that thread you linked are a bit over my head. I tried it with a run of each loop and use of the String class before the timed loops to 'warm it up' as some suggested, but no matter what the first one is always longer. Why is the first one timed longer regardless of which loop it is? And does this mean that my loop1 and loop2 are roughly equivalent in speed? What is the preferable thing to do, redeclare a reference inside a method each time it runs, or reuse an instance field? – pyjamas Sep 04 '15 at 18:00

1 Answers1

4

Setting a local variable is much faster, especially when it doesn't do anything. What you are timing is how long it takes for the JIT to detect and optimise away the code. You will find if you double the length of the loop it won't take much longer.

When you set a static variable, it is harder for the JIT to optimize it away.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130