2

Background

Recently I posted an answer recommending something like:

x = x + 2;

Someone commented "Please use x += 2; instead."

Having studied assembly language and compilers to some degree, I always assumed that these two statements would be reduced to the same assembly instructions. Therefore, I also thought that there would be no performance difference between the two, and that the only difference was a matter of opinion and style.

After recieving the above comment, I was curious, and did a quick google and SO search, which returned nothing.

My Question

Is there any performance difference between x = x + 2; and x += 2 in java? Or is the only difference in readability and style, making the choice between the two a matter of opinion?

Please provide evidence, not opinion.

nhouser9
  • 6,730
  • 3
  • 21
  • 42
  • 1
    You're worrying about _nanoseconds_ here. Premature optimization. – Jim Garrison Oct 02 '16 at 21:38
  • A simple "why?" as answer to that comment would have been more productive. – k5_ Oct 02 '16 at 21:39
  • 1
    Your code was `x = (x + 2);` and my comment wasn't about performance, it was about readability (since it also avoids the redundant parenthese). – Tom Oct 02 '16 at 21:40
  • @JimGarrison I'm not looking to change all of the statements in my codebase, I'm looking to gain a theoretical understanding. – nhouser9 Oct 02 '16 at 21:40
  • Btw you can think about using this as a dupe: http://stackoverflow.com/questions/8710619/javas-compound-assignment-operators. It isn't about performance, but shows that `+=` is different. – Tom Oct 02 '16 at 21:44
  • 1
    You could write it in Java, compile it and decompile the bytecode to have the evidence you need. – Francis Straccia Oct 02 '16 at 21:53

4 Answers4

2

Below is what Eclipse compiler does (see the edit below).

Java code:

public static void x( int x)
{
    x = x + 2;
}

Byte code:

public static void x(int);
  Code:
     0: iinc          0, 2
     3: return

Java code:

public static void x( int x)
{
    x += 2;
}

Byte code:

public static void x(int);
  Code:
     0: iinc          0, 2
     3: return

As you can see, they compile to the same byte code. Java compiler heavily optimizes your code, so do not try to optimize it for trivial things, especially at the expense of readability.

Edit: Turns out not all compilers compile these statements to the same byte code. However, the original point still stands. Do not try to optimize your Java code for trivial things, especially at the expense of readability; because JIT compiler heavily optimizes your code while compiling the byte code into native machine code, even if some Java compilers skip some optimizations.

uoyilmaz
  • 3,035
  • 14
  • 25
  • 2
    What version of java are you using? I got different bytecode for those 2 statements – Jorn Vernee Oct 02 '16 at 22:03
  • I'm using version 1.7.0_51. What version are you using? – uoyilmaz Oct 02 '16 at 22:19
  • I'm using version 1.8.0_101. – Jorn Vernee Oct 02 '16 at 22:20
  • 2
    Yes, 1.8.0_101 seems to generate a different byte code with 3 more instructions for x = x + 2 – uoyilmaz Oct 02 '16 at 22:36
  • 1
    Actually, 1.7.0_51 also seems to generate the same byte code as 1.8.0_101. The one generating the same byte code for two different styles was Eclipse compiler. Sorry for the confusion. – uoyilmaz Oct 02 '16 at 22:51
  • @uoyilmaz JDK compiler compiles the two samples to **different** bytecode as you and Jorn Vernee agreed in the comments, which makes your answer almost irrelevant: the fact that your Eclipse compiler compiles the samples to the same bytecode does not prove that there's no difference "in java" (OP's wording was a bit vague here, yes, but I think you would agree that Eclipse compiler has no relevance to any production environment); so, would you update your answer to reflect this? – starikoff Oct 03 '16 at 14:27
  • Updated the answer – uoyilmaz Oct 04 '16 at 07:52
0

I believe the only difference is readability. When studying this in class we were told thatx += 2 is actually less common.

Answers on this question seem to suggest that it depends on the compiler that you use, the accepted answer says that with most compilers it is identical.

This other question is specific to Java and provides a lot more evidence.

Community
  • 1
  • 1
StarSweeper
  • 397
  • 2
  • 4
  • 28
  • any evidence that the compiler treats them the same? – nhouser9 Oct 02 '16 at 21:41
  • 1
    *"is actually less common"* I doubt that ... highly. – Tom Oct 02 '16 at 21:41
  • @Tom I went to a good engineering university and most of my friends and I never write += for simple integer addition; we consider it much less readable. – nhouser9 Oct 02 '16 at 21:46
  • @nhouser9 Then I would reconsider calling it "good engineering university" ;P. (JK) I only see programming fresher using `x = x + ...` and they changed that after gaining experience and favored the advantages (implicit typecasting for example). If *you* prefer `x = x + 2`, then keep using that. It isn't wrong. – Tom Oct 02 '16 at 21:55
  • @nhouser9 I added a link that should help – StarSweeper Oct 02 '16 at 22:03
  • 2
    @Tom To be honest I can't remember if the prof was talking about out in the real world or within the department, but x = x + 1 is certainly more intuitive and therefore probably more popular with students. – StarSweeper Oct 02 '16 at 22:06
  • 1
    @StarSweeper *"more popular with students"* I agree on that and it is also better to teach `x = x + 1` at first, especially if the students never programmed before. – Tom Oct 02 '16 at 22:11
  • @Tom right. it's better to teach it to students because its easier to understand and more intuitive. in short, more readable. – nhouser9 Oct 02 '16 at 22:15
  • @nhouser9 It's exactly as intuitive as saying "take x, add 1, and store it in x` instead of "increase x by 1". It's better for beginners, but worse for non-beginners (reading more code simply must take longer, assuming the code is simple). It's especially bad when you replace `x` by something more complicated. – maaartinus Oct 03 '16 at 17:13
  • @maaartinus just to be perfectly clear, I am not arguing that `x=x+1` is better than `x+=1`. I am arguing that it is a matter of opinion. – nhouser9 Oct 03 '16 at 17:53
  • @nhouser9 My *opinion* is that there are good *objective* reasons for using `x +=1 ` and even more for `a[i][f(j)] += 1`. But that's just my opinion and I'm fine with you disagreeing. – maaartinus Oct 03 '16 at 19:13
0

Generated bytecodes for the two pieces of code are different on my machine (as are most likely on yours), but that doesn't matter. First, machine code actually run by JVM after optimizations might be the same; second, in practice you won't notice any difference. Try benchmarking it yourself (this PDF presentation explains why you shouldn't), say, in a loop, and you'll see that you get all sorts of results that can differ n-fold between runs and/or after minor changes, and that happens in a surrounding that you made as predictable as you could. Imagine what happens in the real code where any of these lines is by no chance a substantial CPU-spender.

Running a proper JMH microbenchmark for this code says that it runs in ~3-4 nanoseconds in both variants (together with loading the initial value from a field and returning result from the method, or else the whole method might be thrown away). I'm a bit skeptical that some framework can measure time with such accuracy on my desktop, but what I do think is that either that is true or actual timings of these two pieces of code are drowned in other costs (calling a method? loading a value? returning a value?).

Benchmark        Mode  Cnt       Score      Error   Units
MyBenchmark.f1  thrpt   30  281747,576 ± 9748,881  ops/ms
MyBenchmark.f2  thrpt   30  289411,317 ± 8951,254  ops/ms

For the sake of completeness, the benchmark I used is

import org.openjdk.jmh.annotations.*;
import java.util.concurrent.*;

@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MyBenchmark {

    public int a = 0xDEADBEAF;

    @Benchmark
    public int f1() {
      int x = a;
      x += 2;
      return x;
    }

    @Benchmark
    public int f2() {
      int x = a;
      x = x + 2;
      return x;
    }
}

Run with 10 warmup iterations, 10 measuring iterations, 3 forks.

starikoff
  • 1,601
  • 19
  • 23
-1

The compiler executes both the statements in the same fashion and there is no difference in the execution time or performance whatsoever. x+=2 is interpreted by the compiler as x = x+2 and should have no difference in exec time.

Kushagra
  • 626
  • 6
  • 20