0

Given the following Java code, will the JRE optimizer replace the call to max with a call to Math.max?

Unoptimized code

public static void main(String[] args) {
  int max = max(3, 5);
}

public int max(int x, int y) {
  if (x < y) {
    return y;
  }
  else {
    return x;
  }
}

Optimized code

public static void main(String[] args) {
  int max = Math.max(3,5)
}
RouteMapper
  • 2,484
  • 1
  • 26
  • 45
  • Optimize by calling a completely unrelated method? – Sotirios Delimanolis Dec 11 '13 at 22:02
  • I'm wondering if it is smart enough to understand what the functional semantics of the `max` function are. If it is, shouldn't it replace it with a call to Math.max or some other equivalent code? – RouteMapper Dec 11 '13 at 22:05
  • It could be smart enough, but no such smartness is free (it all costs time). This optimization is something you can do yourself easily and the compiler concentrates on things you can't. Some optimizations could be done by recognizing a pattern, but recognizing a call to a specific method is much easier... that's what intrinsics are about, see my answer. – maaartinus Dec 12 '13 at 00:39
  • A trustworthy compiler SHOULD NOT replace a call to a user method with a call to a library routine, unless it can FULLY analyze all of the possible side-effects and prove that the two are equivalent. And even if a compiler could do this, it's not worth the compiler writer's time to make it do it, since the opportunities (except for special-case compilers) would be so rare. Far easier for the user to pre-process the source to replace one call with the other. – Hot Licks Dec 12 '13 at 00:53
  • Now, if `max` were simply coded to invoke `Math.max`, then an optimizing (just-in-time) compiler very likely *would* inline the call and invoke `Math.max` directly. – Hot Licks Dec 12 '13 at 00:54

2 Answers2

5

No. How would the compiler know they are the same?

What makes you think Math.max would be faster anyway? There is no reason it would perform faster than your function.

The compiler may well inline a simple function like that though - but that is down to the compiler.

Imagine how many libraries there are in a standard program. How much effort would the compiler need to go to to scan all those libraries for identical code fragments. Then see how tiny the gains from identifying them would be.

Now also consider the case of multiple libraries where both define this method. The compiler needs to leave both because otherwise one library becomes dependant on the other and what would happen if in the future one library changed or removed its definition of the method.

It's a huge messy can of worms for no real benefit in the end.

Tim B
  • 40,716
  • 16
  • 83
  • 128
3

There's a very good reason for Math.max to be faster than a handwritten method: It's on the list of intrinsic methods. As it's a very simple operation, there might be no gain on a given CPU, but using it is probably a good idea.

For more complex operations there is a huge speed up from using intrinsics. For example, the Java code of Long.numberOfLeadingZeros(long) is pretty long and make take a dozen cycles (or more with some branch mispredictions). As the Hotspot JVM knows this method and there's a corresponding i86 instruction, you can get it in a single cycle (even leaving room for other instructions to be executed concurrently).

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Well, the version of the source is a few years old, but here is Math.max: `public static int max(int a, int b) { return (a >= b) ? a : b; }`. Pretty much identical to the OP's method. And, frankly, a decent JITC should be able to optimize that to about 3 instructions. – Hot Licks Dec 12 '13 at 02:13
  • I don't know what's the reason for using intrinsincs here, but the optimization is non-trivial: When the branching probability is close to 0 or 1, you should use a conditional branch, but otherwise a conditional move is better (possibly much better). See also [this question](http://stackoverflow.com/questions/19689214/strange-branching-performance) of mine. – maaartinus Dec 12 '13 at 02:39
  • But a good optimizer can figure out to use the conditional move for such a simple case. – Hot Licks Dec 12 '13 at 03:53