views:

172

answers:

6

For a variable used in a function that is called very often and for implementation in J2ME on a blackberry (if that changed something, can you explain)?

class X {
    int i;
    public void someFunc(int j) {
        i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

or

class X {
    static int i;
    public void someFunc(int j) {
        i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

or

class X {
    public void someFunc(int j) {
        int i = 0;
        while( i < j ){
            [...]
            i++;
        }
    }
}

I know there is a difference how a static versus non-static class variable is accessed, but I don't know it would affect the speed. I also remember reading somewhere that in-function variables may be accessed faster, but I don't know why and where I read that.

Background on the question: some painting function in games are called excessively often and even small difference in access time can affect the overall performance when a variable is used in a largish loop.

Update

I setup a small test (code below) and ran it on a real device to see what the results are like. I ran 10000 calls to a function that looped 10000 times accessing a variable.

  • if the variable was in-function it took ~9250 ms to run
  • if the variable belonged to the class, it took ~ 21700 ms to run
  • if the variable belonged to the class but was static it tool ~210000 ms to run.

I don't know how relevant are the results of the test, if they would hold in a real-world program and if there is no other external factor at play. But, assuming they do, since it matches the most commonly held view here, then there is a sizeable difference between the access times.

Does this fall under premature optimizing? Maybe, but it also seems like a useful guideline to use in-function variable as much as possible. Even copying a class-variable to an in-function one seems like it could impact the execution time.

   final static int MAX = 10000;
   private void runTest()
   {
       long startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test1(MAX);
       test1.setText(""+(System.currentTimeMillis()-startTime));

       startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test2(MAX);
       test2.setText(""+(System.currentTimeMillis()-startTime));

       startTime = System.currentTimeMillis();
       for(int count = 0; count < MAX; count++)
           test3(MAX);
       test3.setText(""+(System.currentTimeMillis()-startTime));

   }

   void test1(int j)
   {
       int i = 0;
       while(i < j)
       {
           i++;
       }
   }
   int i2;
   void test2(int j)
   {
       i2 = 0;
       while(i2 < j)
       {
           i2++;
       }
   }
   static int i3;
   void test3(int j)
   {
       i3 = 0;
       while(i3 < j)
       {
           i3++;
       }
   }
+8  A: 

They have completely different semantics - do you want the value to be part of the state of the class, part of the state of instances of the class, or local to the method?

The JIT has more opportunity to optimise the last version as it knows everything about where the variable might be used (and doesn't need to worry about other threads accessing it). I'd say it's likely to be the fastest.

You should really test though - and in general, write the most readable code first and see whether you've actually got a bottleneck before trying this sort of micro-optimisation.

Jon Skeet
I agree on the semantics, but the variable is only used inside the function. I was wondering if moving it out could make this faster. I will perform some tests and posts the results.
ADB
I don't think you can count on having an optimizing JIT on Java ME.
Michael Borgwardt
@Michael: Possibly not - but it's hard to see how giving the platform tighter control over the variable would make it perform *worse*.
Jon Skeet
+2  A: 

Personally, I think you aren't going to see any noticeable difference between the three. Why not just try out all three and run some performance tests? This is the only way you will know for sure, since the way the JVM optimizes things under the covers might be non-intuitive.

I find it hard to believe this is your performance bottleneck. My approach would be to write it in the most logical way, and look for optimizations elsewhere.

dbyrne
+3  A: 

You should thoroughly profile the code before you even think about this kind of micro-optimization. And then, implement and measure the effects of any possible micro-optimizations.

It is too difficult to predict which (if any!) of the three versions will be faster on your particular platform.

Stephen C
A: 

Or you could just use the traditional for loop that reclaims this memory as soon as the loop ends:

class X {
    public void someFunc(int j) {
        for(int i = 0; i < j; i++){
            [...]
        }
    }
}
R. Bemrose
+1  A: 

I also remember reading somewhere that in-function variables may be accessed faster, but I don't know why

Local variables can be kept in a register, the fastest memory that exists. Unless you have a very smart JIT, instance and class fields have to be in main memory (or a cache) since they can be visible to other threads.

Since it's also the best solution from a code cleanliness point of view, you should definitely go with a local variable.

Michael Borgwardt
A: 

Unless your target platform has some very odd JVM implementation, the order of performance is:

  • local variable
  • static/object member

The reason local variables offer the best performance is that they:

  • Are specially supported by shorter bytecodes by the JVM
  • No additional information is required to access them (object members must be addressed using the this reference, while static members need the class reference)
  • Are only visible to the local thread and thus the JIT can perform various optimizations on them (like putting them into a register)

It may also noteworthy that method parameters are treated just the same as local variables on the bytecode level.

Durandal