Question

Which is the best method for increasing a counter (integer) in java. I am interested in the cost of the operation.

int j = 0;
j = j + 1;

or

int i = 0;
i++;

It gives almost the same for small programs, but it differs for big calculations, the thousands of iterations.

Was it helpful?

Solution 3

When you talk about increment or decrement , the first thing which come in mind is the operator used for increment or decrement i.e ++, --

In your first case of course that will do the increment job for you , but its indirect approach to increment techniques, and compiler will need to do two jobs, 1) Addition 2) Assignment.

In Second one the compiler Knows that it is increment operator , so it will increment that variable.

OTHER TIPS

In deference to the other answers posted, I feel you deserve to see an example of all three techniques in action. the following is highly situational, but none-the-less demonstrates what can happen:

The Code

#include <stdio.h>>

int i=1;

int main()
{
    printf("i=%d\n", i);

    printf("i++ : %d\n", i++);

    printf("++i : %d\n", ++i);

    i = i + 1;
    printf("i=i+1 : %d\n", i);

    return 0;
}

The Tools

Using clang 3.3 optimization set to -O2

The Assembly Listing

Cleaned and annotated for consumption:

; Basic printf()
movl    _i(%rip), %esi
leaq    L_.str(%rip), %rdi
xorb    %al, %al
callq   _printf

; post-increment (i++)
movl    _i(%rip), %esi
leal    1(%rsi), %eax
movl    %eax, _i(%rip)
leaq    L_.str1(%rip), %rdi
xorb    %al, %al
callq   _printf
leaq    L_.str2(%rip), %rdi

; pre-increment (++i)
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
xorb    %al, %al
callq   _printf
leaq    L_.str3(%rip), %rdi

; traditional (i = i + 1)
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
xorb    %al, %al
callq   _printf

The Difference

The stark difference is the storage of a temporary containing the prior value of i before increment in the case of i++ vs ++i. This is solely because said-temp is used as an argument to the printf() function invoke. Also note that in both the pre-increment and traditional mechanic, the resulting optimized assembly is identical (movl, incl, movl).

So does it make a difference if the post-increment operation is not evaluated ?

int main()
{
    i++;
    printf("i=%d\n", i);

    ++i;
    printf("i=%d\n", i);

    i = i + 1;
    printf("i=%d\n", i);

    return 0;
}

With the resulting assembling being:

; post-increment
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
leaq    L_.str(%rip), %rbx
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

; pre-increment
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

 ; traditional
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

Note that the rbx magic you see is unrelated and simply a way for caching the shared format string for printf(). In all three cases the identical code (movl,incl,movl) is used.

Conclusion

For a stand-alone statement, clang 3.3 will optimize all three to the same resulting code. If you introduce an evaluation dependance, post-increment and pre-increment can (and likely will) emit differing code. If your increment is a stand-alone statement, it makes no difference which you choose.

Using prefix operators is faster than using postfix. i.e ++i is faster than i++.

For ++i, the value is increased and the new value is returned.

For i++, the value is increased, but the old value is returned. The performance difference comes as the older value needs to be stored first.

Not sure about the first method since I have never incremented a counter that way (I am sure someone else will come in there) but for the second it would be better to use ++i than i++. The reasons have already been answered for that one in this question, but in a nutshell, i++ makes a copy of i whereas ++i works directly on the variable itself.

++i is faster than other methods.

So your code will be :

int i = 0;
++i;

Here is some Java source code:

    int i = 0;

    i = i + 1;

    i += 1;

    ++i;

    i++;

And here is the corresponding Java byte code, obtained by javap -c:

 0: iconst_0      
 1: istore_1      

 2: iload_1       
 3: iconst_1      
 4: iadd          
 5: istore_1      

 6: iinc          1, 1

 9: iinc          1, 1

12: iinc          1, 1

As you can see, the last three syntactic forms compile to the same JVM instruction iinc. The first one generates more byte code, but I'd be surprised if the JIT compiler didn't optimize that difference away.

@Modred: For the use of two methods that you quoted the result is not the same in the case of affectaion. for the following code the result isn't the same:

int i = 0, j = 0,k = 0;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';
j = i++;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';
k = ++i;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';

OUTPUT

i = 0 ,j = 0 ,k = 0
i = 1 ,j = 0 ,k = 0
i = 2 ,j = 0 ,k = 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top