简体   繁体   中英

Java for loop performance

What is better in for loop

This:

for(int i = 0; i<someMethod(); i++)
{//some code
 }

or:

int a = someMethod();
for(int i = 0; i<a; i++)
{//some code
 }

Let's just say that someMethod() returns something large.

First method will execute someMethod() in each loop thus decreasing speed, second is faster but let's say that there are a lot of similar loops in application so declaring a variable vill consume more memory.

So what is better, or am I just thinking stupidly.

The second is better - assuming someMethod() does not have side effects .
It actually caches the value calculated by someMethod() - so you won't have to recalculate it (assuming it is a relatively expansive op).

If it does (has side effects) - the two code snaps are not equivalent - and you should do what is correct .

Regarding the "size for variable a" - it is not an issue anyway, the returned value of someMethod() needs to be stored on some intermediate temp variable anyway before calculation (and even if it wasn't the case, the size of one integer is negligible).

PS
In some cases, compiler / JIT optimizer might optimize the first code into the second, assuming of course no side effects.

If in doubt, test. Use a profiler. Measure.

Assuming the iteration order isn't relevant, and also assuming you really want to nano-optimize your code, you may do this :

for (int i=someMethod(); i-->0;) {
  //some code
}

But an additional local variable (your a ) isn't such a burden. In practice, this isn't much different from your second version.

If you don't need this variable after loop, there is simple way to hide it inside:

for (int count = someMethod (), i = 0; i < count; i++)
{
    // some code
}

It really depends how long it takes to generate the output of someMethod(). Also the memory usage would be the same, because someMethod() first has to generate the output and stores this then. The second way safes your cpu from computing the same output every loop and it should not take more memory. So the second one is better.

I would not consider the memory consumption of the variable a as a problem as it is an int and requires 192 bit on a 64 bit machine. So I would prefer the second alternative as it execution efficiency is better.

The most important part about loop optimizations is allowing the JVM to unroll the loop. To do so in the 1st variant it has to be able to inline the call to someMethod() . Inlining has some budget and it can get busted at some point. If someMethod() is long enough the JVM may decide it doesn't like to inline.

The second variant is more helpful (to JIT compiler) and likely to work better.

my way for putting down the loop is: for (int i=0, max=someMethod(); i<max; i++){...}

max doesn't pollute the code, you ensure no side effects from multiple calls of someMethod() and it's compact (single liner)

If you need to optimize this, then this is the clean / obvious way to do it:

int a = someMethod();
for (int i = 0; i < a; i++) {
    //some code
}

The alternative version suggested by @dystroy

for (int i=someMethod(); i-->0;) {
    //some code
}

... has three problems.

  • He is iterating in the opposite direction.

  • That iteration is non-idiomatic, and hence less readable. Especially if you ignore the Java style guide and don't put whitespace where you are supposed to.

  • There is no proof that the code will actually be faster than the more idiomatic version ... especially once the JIT compiler has optimized them both. (And even if the less readable version is faster, the difference is likely to be negligible.)

On the other hand, if someMethod() is expensive (as you postulate) then "hoisting" the call so that it is only done once is likely to be worthwhile.

I was a bit confused about the same and did a sanity test for the same with a list of 10,000,000 integers in it. Difference was more than two seconds with latter being faster:

int a = someMethod(); for(int i = 0; i<a; i++) {//some code }

My results on Java 8 (MacBook Pro, 2.2 GHz Intel Core i7) were:

using list object: Start- 1565772380899, End- 1565772381632

calling list in 'for' expression: Start- 1565772381633, End- 1565772384888

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM