2010-01-20 28 views
21

¿Cuál es más rápido en Java y por qué?¿Math.max (a, b) o (a> b)? A: b son más rápidos en Java?

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

(Esto se le preguntó en una entrevista.)

+18

Me pregunto qué esperaba el entrevistador al hacer esa pregunta. – Seth

+0

debe preguntar cuál es más fácil de leer rápidamente, que es mucho más importante. Math.max (a, b) EXPLICAMENTE muestra que tiene una mejor intención, por lo que es la respuesta correcta –

+13

Realmente odio cuando las personas preguntan a un abogado de idiomas en una entrevista. ¿Alguien realmente piensa que tu habilidad para ser un programador productivo está fuertemente correlacionada con tu habilidad para memorizar las minucias de una especificación de lenguaje? – dsimcha

Respuesta

20

Math.max(a, b) es una función estática (es decir, ninguna sobrecarga de llamadas virtual) y es probable que se inlined por la JVM a las mismas instrucciones que (a > b) ? a : b.

+3

The el compilador no alinea las instrucciones de JVM, el perfilador de JIT inserta el código de máquina :) –

+0

@BlueRaja: He editado mi respuesta, ya que técnicamente tienes razón (creo), pero en realidad es un detalle menor en el contexto de la pregunta . – dsimcha

+1

IIRC, el JIT en realidad no realizará ninguna optimización hasta que el bloque en cuestión se haya ejecutado muchas (miles) veces. La única respuesta segura a las preguntas de rendimiento (especialmente en Java) es: "Depende ..." – TMN

20

Here es el código para Math.max() en Java:

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

Por lo tanto, el código sería probablemente (casi) exactamente la misma velocidad.

(seamos honestos, si usted se está preocupando de mejoras en la velocidad a un nivel tan bajo, es probable que tenga problemas mucho mayores en su código.)

+1

En realidad, el código que se da a la pregunta todavía se bifurca cuando 'a' y' b' son iguales, lo que empeoraría. Sé que alguien va a decir algo acerca de las búsquedas de métodos pero, honestamente, no use Java si eso le importa. Cuando alguien ve 'Math.max', ellos saben lo que estás haciendo y eso es lo que importa. –

+1

¿Por qué la bifurcación en 'a == b' sería peor? Supongamos que 'a' y' b' son realmente '' aleatorios''. Entonces, ¿no se ramificará 'a> b' tan a menudo como 'a> = b'? –

+4

@Sinan: cuando miras el bytecode puedes ver que el operador condicional siempre se bifurca, así que usar '> =' en vez de '=' simplemente haría que utilizara la otra ruta cuando los valores son iguales. Y las máquinas virtuales Java actuales también pueden lograr un rendimiento increíble para operaciones de bajo nivel que a veces es difícil de superar, incluso con C o ASM. El alto rendimiento y Java ya no son necesariamente una contradicción si sabes qué evitar. – x4u

-1
No

la misma. Cuando escribe (a > b) ? a : b, no tiene una llamada de función adicional, por lo que será más rápido. Es el equivalente de crear en C++. Pero esto no hará ninguna diferencia en la vida real. Math.max(a,b) es más legible, así que lo usaría.

+0

no, consulte dsimcha answer –

+0

Cualquier llamada a función agregará sobrecarga, incluso si no es virtual. Si examina el código de máquina, verá que cuando se llama a la función, los parámetros se empaquetan en la pila; cuando la función volverá, el valor del resultado se extrae de la pila. Todo esto consumirá ciclos de CPU. – XMLDUDE

+2

Lo que usted describe es exactamente lo que la optimización interna está diseñada para evitar. Las funciones diminutas como max casi siempre están en línea con cualquier compilador decente o JIT. – dsimcha

9

preguntas de desempeño siempre llaman para una prueba antes de poder empezar a especular:

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); 
} 

Esto se ejecuta en mi máquina de 6 segundos con Math.max() y 3,2 segundos con ?: en el último servidor 1.6.1 x64 Sun JVM. Entonces ?: es realmente más rápido. Contrariamente a todas las esperanzas que nos gustaría poner en los JIT que realmente se han vuelto sorprendentes en el momento en que todavía no captan todo.

EDITAR: Por curiosidad también probé este código con el cliente de 32 bits JVM 1.6.1 en la misma máquina y con esto ambas versiones se ejecutan en 7 segundos. Por lo tanto, probablemente no sea la invocación al método lo que no se alinee, pero el JIT del servidor parece ser capaz de realizar algunas optimizaciones adicionales para este caso de prueba en particular que no puede detectar cuando hay una llamada de método involucrada.

+1

Esa es una diferencia de menos de un ciclo por iteración de bucle. Probablemente no significativo. –

+0

Ah, y por supuesto 'Math.max' se define de forma ligeramente diferente a su alternativa, y casi siempre sigue el mismo camino (puede causar una desoptimización rara cuando no) –

+0

Lo ejecuté con'> = 'y'> 'en la condición y el tiempo de ejecución se mantuvo igual. – x4u

3

He estado en el extremo receptor de este tipo de preguntas y suelen ser más sobre cómo se responde la pregunta que cuál es la respuesta "correcta".

1

Si hubiera hecho una pregunta de este tipo en una entrevista, hubiera esperado que el candidato me dijera que las dos expresiones pueden no dar el mismo resultado para todos los tipos posibles de ay b.

+0

¿Qué? No veo cómo es ese el caso. Los operadores de comparación solo trabajan en primitivas, por lo que el comportamiento está bien definido (a menos que me falta algo). Por favor explique. –

+1

Te faltan dobles, flotantes, Double.NaN y Float.NaN. –

+0

Y la diferencia entre cero positivo y negativo. – jarnbjo

1

La pregunta original no especifica el tipo de los argumentos. Esto es importante porque la definición de max (y min) para argumentos de coma flotante es más compleja. Para el punto flotante (doble o flotante) es probable que el método Math.max sea más lento, pero también puede devolver un resultado diferente si uno de los argumentos es NaN.

0

No confíe en especulación. En cambio, punto de referencia su caso de uso particular.

Algunos se pasa por alto fácilmente los detalles en muchas de las otras respuestas:

Si bien se puede ver una fuente de Java de Math.max, esto es en realidad no siempre lo que se utilizará. Este método tiene una intrínseca versión en casi todos los JRE. Consulte el source code of Hotspot in JDK7, vmSymbols.hpp para obtener una lista de dichos intrínsecos.

Por lo que puedo decir, Hotspot intentará una serie de optimizaciones cuando vea una declaración max o min; en particular para optimizar, p. arraycopy. Entre otros, en realidad optimizará Math.max(same, same) de distancia.

En otros casos, sin embargo, puede no optimizar mucho; (a<=b)?a:b puede ser más rápido. He estado haciendo benchmarking un poco, y de hecho a menudo encuentro que esto es más rápido. Pero YMMV, y definitivamente depende del contexto si Hotspot puede optimizar uno mejor o el otro. También variará de la versión de hotspot a la versión de hotspot ...

Cuestiones relacionadas