30

Which one is faster in Java and why?

  1. Math.max(a,b)
  2. (a>b)?a:b

(This was asked in an interview.)

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
giri
  • 26,773
  • 63
  • 143
  • 176
  • 23
    I wonder what the interviewer was hoping to gain by asking such a question. – Seth Jan 20 '10 at 17:54
  • you should ask back which one is easier to read quickly, which is way more important. Math.max(a,b) EXPLICTLY shows it's intent better so that is the correct answer –  Jan 20 '10 at 17:55
  • 18
    I really hate when people ask language lawyer questions at an interview. Does anyone really think your ability to be a productive programmer is strongly correlated with your ability to memorize the minutiae of a language spec? – dsimcha Jan 20 '10 at 17:56
  • Who cares and why does anyone care? – Sinan Ünür Jan 20 '10 at 17:58
  • 8
    The correct response to this question is (from a compiler background) it depends on what the optimizer choose to do with the function call. There is **NO WAY** to determine the speed optimization of the above calls without knowing 1. The execution context, and 2. the optimizers preferred inline method for the calling arguments. Educated guesses (as below) can be made, but they are just guesses. I agree with @dsimcha these questions dont really tell anything about your abilities. – GrayWizardx Jan 20 '10 at 18:00
  • 5
    I can write you a jvm where one is substantially faster than the other, or vice versa ;) – bertolami Jan 20 '10 at 18:01
  • 1
    This is perhaps an insight into the code you are about to work with. I can see the employers code being full of bugs whereby (a < b) has been written accident, but saves 13 processor cycles a week. – reccles Jan 20 '10 at 18:07
  • @dsimcha: WTF has this got to do with language spec? – Tom Hawtin - tackline Jan 20 '10 at 18:09
  • 5
    @Seth: I would *hope* that the interviewer is trying to determine whether the interviewer indulges in pointless microoptimisation. – Tom Hawtin - tackline Jan 20 '10 at 18:10
  • 2
    I hear you, @dsimcha -- but I really hate **more** when people ask questions here that they could easily inform by *running a simple test in their own environments*. How hard would it have been, girinie, for you to run a test between the two options? – delfuego Jan 20 '10 at 18:19
  • Argh, it's this thing rearing its head again: http://www.mydeveloperconnection.com/html/JavaTrap.htm Just like it did here: http://stackoverflow.com/questions/1656506/which-of-these-pieces-of-code-is-faster-in-java – Kevin Bourrillion Jan 20 '10 at 21:17
  • newer related question: http://stackoverflow.com/questions/22752198/java-math-min-max-performance – Ray Tayek Feb 26 '15 at 07:05
  • I've been on the receiving end of this type of question and they are usually more about how you answer the question than what the 'correct' answer is. –  Jan 20 '10 at 18:29

7 Answers7

30

Here is the code for Math.max() in Java:

public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

So, the code would probably be (almost) exactly the same speed.

(Lets be honest, if you are worrying about speed improvements at such a low level, you probably have far greater problems in your code.)

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 1
    Actually, the code given the question still branches when `a` and `b` are equal which would make it worse. I know someone is going to say something about method lookups but, honestly, don't use Java if you care about that. When someone sees `Math.max` they know what you are doing and that's what matters. – Sinan Ünür Jan 20 '10 at 17:56
  • 1
    Why would branching on `a == b` be worse? Let's suppose that `a` and `b` are truely random `int` s. Then wouldn't `a > b` branch equally as often as `a >= b`? – Thomas Eding Jan 20 '10 at 18:16
  • 4
    @Sinan: When you look at the bytecode you can see that the conditional operator always branches, so using `>=` instead of `=` would just make it use the other route when the values are equal. And current Java VMs can achieve amazing performance also for low level operations that is sometimes hard to beat even by C or ASM. High performance and Java isn't necessarily a contradiction anymore if you know what to avoid. – x4u Jan 20 '10 at 18:21
  • @x4u OK. Thank you for the information. I upvoted @jjnguy's answer at the time for him taking the time to look up what is done in the source. In any case, my point was not that Java is slow, but that there is absolutely no point in worrying about the speed difference between inlining and calling a static method unless there is some horrible bug that you are trying avoid or some other crazy thing. – Sinan Ünür Jan 20 '10 at 18:58
28

Math.max(a, b) is a static function (meaning no virtual call overhead) and will likely be inlined by the JVM to the same instructions as (a > b) ? a : b.

dsimcha
  • 67,514
  • 53
  • 213
  • 334
  • 5
    The compiler does not inline JVM instructions, the JIT profiler inlines the machine code :) – BlueRaja - Danny Pflughoeft Jan 20 '10 at 17:53
  • @BlueRaja: I've edited my response, since technically you're right (I think), but it's really a minor detail in the context of the question. – dsimcha Jan 20 '10 at 17:55
  • 2
    IIRC, the JIT won't actually perform any optimization until the block in question has been executed many (thousands?) times. The only safe answer to performance questions (especially in Java) is: "It depends..." – TMN Jan 20 '10 at 18:19
  • @TMN: Ok, but assuming you're looking for a **practical** response rather than a legalese response, why would you ever optimize function call overhead for something that's getting called that infrequently? – dsimcha Jan 20 '10 at 18:24
  • Since the question was asked during an interview, I assumed that they were looking for a "legalese"-type response. One possible case could be if you're trying to optimize a last-chance exception handler that should never be invoked, but has to execute quickly if it ever is. I just made that up; of course, in the real world you don't worry about trivial optimizations like that. – TMN Jan 21 '10 at 13:50
  • 1
    Unfortunately, I think it boils down to which special case(s) the optimizer recognizes. For instance, suppose there's a single machine instruction that can do max? And the optimizer recognizes a call to Math.max() and replaces it with that machine instruction, but it *doesn't* recognize `(a>b)?a:b`. Or conversely, the best it can do with Math.max() is to convert it to `(a>b)?a:b` and that conversion takes time. – Edward Falk Jan 10 '16 at 20:45
13

Performance questions always call for a test before you can start speculating:

public static void maxtest()
{
    int res = 0;
    for( int idx = 0; --idx != 0; )
        // res = ( res > idx ) ? res : idx;
        res = Math.max( res, idx );
    System.out.println( "res: " + res );
}

This runs on my machine 6 seconds with Math.max() and 3.2 seconds with ?: on the latest 1.6.1 x64 server Sun JVM. So ?: is actually faster. Contrary to all the hopes we like to put in the JITs that have really become amazing by the time they still don't catch everything.

EDIT: Out of curiosity I also tried this code with the 32 bit client JVM 1.6.1 on the same machine and with this both versions run in 7 seconds! So it's probably not the method invocation that doesn't get inlined but the server JIT seems to be able to do some additional optimizations for this particular test case that it can't detect when there is a method call involved.

x4u
  • 13,877
  • 6
  • 48
  • 58
6

Do not rely on speculation. Instead, benchmark your particular use case.

Some easily overlooked details in many of the other answers:

While you can see a Java source of Math.max, this is actually not always what will be used. This method has an intrinsic version in pretty much every JRE. See the source code of Hotspot in JDK7, vmSymbols.hpp for a list of such intrinsics.

As far as I can tell, Hotspot will try a number of optimizations when it sees a max or min statement; in particular to optimize e.g. arraycopy. Amongst others, it will actually optimize Math.max(same, same) away.

In other cases, however, it may not optimize much; (a<=b)?a:b may then actually be faster. I've been benchmarking a bit, and indeed I often found this to be faster. But YMMV, and it definitely depends on the context if Hotspot can optimize one better or the other. It will also vary from hotspot version to hotspot version...

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • my benchmarks,10 years later, also show `if (a>b) a=b;` to be faster over `a = Math.max(a,b);`, which was unexpected to me. So yeah, benchmarking is mostly the way to go, although of course such micro-optimization benchmarks can vary heavily between systems. – N4ppeL Jul 17 '23 at 12:48
3

If I had asked such a question in an interview, I would have expected the candidate to tell me that the two expressions may not give the same result for all possible types of a and b.

jarnbjo
  • 33,923
  • 7
  • 70
  • 94
3

The original question doesn't specify the type of the arguments. This matters because the definition of max (and min) for floating point arguments is more complex. For floating point (double or float) the Math.max method is likely to be slower, but it also may return a different result if one of the arguments is NaN.

Mark Thornton
  • 1,885
  • 1
  • 12
  • 4
-2

Not the same. When you are writing (a > b) ? a : b you don't have an extra function call, so it will be faster. It's the equivalent of inlining in C++. But this will not make any difference in real life. Math.max(a,b) is more readable so I would use it.

XMLDUDE
  • 480
  • 4
  • 4
  • Any function call will add overhead, even if is not virtual. If you examine the machine code, you will see that when the function is called, the parameters are packed on the stack; when the function will return, result value is extracted from the stack. All this will consume CPU cycles. – XMLDUDE Jan 20 '10 at 18:00
  • 2
    What you describe is exactly what the inlining optimization is designed to get around. Tiny functions like max are almost always inlined by any decent compiler or JIT. – dsimcha Jan 20 '10 at 18:06