-1

Which set of conditions is better for looping in Java? I feel they will do the same thing but I'm not sure if I'm not seeing something under the hood.

For(int i = 0; i < array.length; i++) { }

For(int i = 0; i <= array.length-1; i++) { }

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Tom
  • 1
  • 2
  • 1
    I would prefer the first one; the compiler *might* transform the second to the first. But performing `<=` is more expensive than `<`, not to mention needing to do extra math on every iteration is more expensive than not. Of course, as I mentioned, the compiler might work that out and render the discussion moot. – Elliott Frisch Oct 21 '18 at 01:40
  • @ElliottFrisch I thought the same. I don't understand why I see 2nd option so often then. – Tom Oct 21 '18 at 01:41
  • 1
    Meh. Given two choices where it isn't demonstrable better to pick either, half will pick one and half the other. – Elliott Frisch Oct 21 '18 at 01:42
  • It's really just a notation preference. Eg In set theory do you prefer `[a,b-1]` or `[a, b)`? – flakes Oct 21 '18 at 01:49
  • 1
    The two versions reflect how the programmer was thinking about the problem. Different people think differently. (And in this modern world, we need to deal with the fact that some people think differently than we do ... without branding them "heretics" or "fake news".) – Stephen C Oct 21 '18 at 01:54
  • @ElliottFrisch Why do you say that *"performing `<=` is more expensive than `<`"*? They each have dedicated bytecode instructions (`if_icmple` vs `if_icmplt`), and JIT compiled code does too ([Is < faster than <=?](https://stackoverflow.com/q/12135518/5221149)). – Andreas Oct 21 '18 at 01:55
  • @Andreas On at least one real CPU it's usually more efficient to compare `<` than `<=`, and I mentioned it probably doesn't actually matter in practice (since the compiler would pick the most efficient form if it did matter). – Elliott Frisch Oct 21 '18 at 01:59
  • @StephenC but I'm a PC and you're a Mac. How can we possibly co-exist? – flakes Oct 21 '18 at 02:04
  • 1
    @flake - You are "climate change". You don't exist ... and (for the record) I don't user either Mac or PC :-) (Note - this is intended to be humorous / ridiculous ...) – Stephen C Oct 21 '18 at 02:07
  • And note that the Q&A you linked to 1) is about C / C++ (ahead of time) optimizers not Java (just in time) optimizers, and 2) is (strictly) about comparison with manifest constants not runtime loop invariants. – Stephen C Oct 21 '18 at 02:21
  • @StephenC I was asking Elliott Frisch to backup his assertion. I provided information that bytecode is similar, so no reason for one to be faster than another at that level, and link to answer saying that the same applies to most CPU architectures (which is what JIT compiles to), including the very common x86 architecture. Sure, JIT changes, but if bytecode is the "same" and machine code is the "same", why would you expect a difference from JIT? – Andreas Oct 21 '18 at 02:21
  • 1
    @ElliottFrisch Ok, here's another link: [Is performance of “less/greater than than” better than “less/greater than or equal to”](https://stackoverflow.com/q/27016781/5221149): *"On virtually every modern CPU, there are compare/jumpless and compare/jumplessequal instructions that take exactly the same amount of time"* --- That's now 2 links to articles saying there's no difference, and I have yet to see you provide any reference backing up your statement. If you have one, for "real CPUs", I'm interested in seeing it. – Andreas Oct 21 '18 at 02:24
  • Oh ... I see. Elliot is asserting the other side. I agree there is no sound basis for that. – Stephen C Oct 21 '18 at 02:25
  • @Andreas I have no contemporary article to assert performance difference (since I agree it likely doesn't exist); I seem to recall it existing around the pentium/pentium pro and being measurable with various versions of gcc. I also recall removing Duff's Devices from XFree86 improved performance significantly on modern hardware (since modern CPUs have more registers). – Elliott Frisch Oct 21 '18 at 02:32
  • (*"Sure, JIT changes, but if bytecode is the "same" and machine code is the "same", why would you expect a difference from JIT?"* - Because the JIT compiler developers may have done some work to make the optimizer smarter ... from one version to the next.) – Stephen C Oct 21 '18 at 02:33
  • @StephenC I think you misunderstood me. My question was, given the bytecode is the "same" for `<` vs `<=`, and the CPU targeted by JIT has "same" instructions for `<` vs `<=`, why would you expect any particular version of JIT to cause a performance difference between the two? Yes, there can be performance differences between JIT versions, but why would you expect any single JIT version to cause a performance difference for these "same" operations? – Andreas Oct 21 '18 at 02:39

1 Answers1

1

The fact that you commonly see both two forms is most likely due to a combination of the following:

  • Differences in style preferences. The first form is more concise, and some people would prefer it for that reason.

  • Differences in the way the programmer was thinking about the problem.

  • Differences in the way the programmer thinks that the reader will think about the problem. (Like "I know that array indexes go to array.length - 1 and I want the reader to see that I have taken that into account.")

  • A (probably mistaken) belief that one version is more efficient than the other.


I say "probably mistaken" because the consensus is that a modern Java JIT compiler is likely to optimize the two forms into native code that has equivalent performance. I am stating this without providing evidence1 because I am not aware of any counter-evidence2.

1 - Evidence could be obtained by proper benchmarking, or by carefully analyzing the native code emitted by the JIT compiler. Examining bytecodes won't prove anything.

2 - If there was counter-evidence ... that this made a difference ... I claim that it would be common knowledge!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216