Are for-loops in Java faster when run backwards?

283 Views Asked by At

While going through the collections code in JDK, wherever looping is used, it is done in reverse way like this:

for (int i = size-1; i >= 0; i--) {...}

Is there any performance related thing or just JDK has adopted it like this?

2

There are 2 best solutions below

0
On BEST ANSWER

There does not seem to be any performance benefit in Java, in general. (Also, the assertion that the JDK code does reverse looping a lot seems to be unfounded.)

See all the linked similar/duplicate questions, such as Why does decrement loop runs faster than increment loop?

There are also some articles online benchmarking the performance of different loop types, based on different collection types. Like https://www.trinea.cn/android/arraylist-linkedlist-loop-performance-en/

1
On

As mentioned by @tkruse, calling collection.size (); means you do the following every iteration:

  1. memory access
  2. function call
  3. (other instructions inside function)
  4. memory access
  5. return

Whereas, if you initialize i = collection.size () - 1; it will only be done once.

I am not familiar with Java bytecode but bytecode is somewhat similar to assembly code such that it will be translated to machine code. As such, it is worth mentioning that memory access is slower than register access and, in some cases, comparing to any value other than 0 can have an additional instruction per iteration.

Here's an example using NASM:

i++ version

    xor eax, eax        ;i = 0
  label:
    mov ebx, [size]     ;temp = size
    sub ebx, eax        ;temp - i (Note: A >= B == 0 >= B - A)
    jle end             ;temp <= 0 goto end
    inc eax             ;i ++
    jmp label           ;temp > 0 goto label
  end:

i-- version

    mov eax, [size]     ;i = size
    dec eax             ;i = size - 1
  label:
    cmp eax, 0          ;i < 0?
    jl end              ;i < 0 goto end
    dec eax             ;i --
    jmp label           ;i >= 0 goto label
  end: