2009-11-25 34 views
18

Estoy iterando a través de una matriz y clasificándola por valores en días de la semana.¿Qué es más rápido: muchos ifs, o si?

Para hacerlo uso muchas declaraciones if. ¿Hay alguna diferencia en la velocidad de procesamiento si uso muchos if s, en comparación con un conjunto de declaraciones else if?

+1

no sé acerca de la velocidad de procesamiento, pero si usted tiene tantos si los bloques, tal vez usted debería considerar el uso de una sentencia switch. Especialmente para algo así como los días de una semana. –

+0

Hay un cambio de función masivo al cambiar de muchas sentencias if a una instrucción if-elseif. Piensa en lo que realmente hace tu código. –

Respuesta

41

Sí, utilice una persona si, considere el siguiente código:

if(predicateA){ 
    //do Stuff 
} 
if(predicateB){ 
    // do more stuff 
} 

de

if(predicateA){ 
    // 
} 
else if(predicateB){ 
    // 
} 

en el segundo caso si predicateA es verdadero, predicateB (y cualquier predicado adicional) no necesitará ser evaluado (y entonces el código completo se ejecutará más rápido), mientras que en el primer ejemplo si predicateA es t rue, predicateB siempre será evaluado, y también puede obtener sorpresas inesperadas si predicateA y predicateB no son mutuamente exclusivos.

+1

Tendría que haber una cantidad sustancial de condiciones para ver realmente una diferencia en el rendimiento; sin embargo, +1 como si fuera la forma adecuada de todos modos. – James

+5

En realidad, su ejemplo es incorrecto, porque no harán lo mismo si PredicateA y PredicateB pueden ocurrir. solo ejecutará el primero y saldrá. mientras que el primer código ejecutará ambos. –

17

Dudo que una micro optimización como esta haga una diferencia mensurable en su código.

Su algoritmo de clasificación es más probable que sea la fuente de un problema de rendimiento. El algoritmo de clasificación que elijas será crítico, no muchos "si" frente a "otro si".

ACTUALIZACIÓN:

Las observaciones hechas por otros sobre "else if" ser una mejor opción, debido a su temprana salida y características de lógica exclusivos, sugieren que se prefiere en "si" en este caso.

Pero el punto sobre la elección del algoritmo sigue en pie, a menos que su conjunto de datos sea muy pequeño.

Es obvio que O (log n) sería mejor que O (n^2), pero el tamaño del conjunto de datos también es importante. Si tiene solo algunos elementos, es posible que no note la diferencia. En ese caso, codificar un método ineficiente de la forma más limpia, más fácil de leer, más fácil de entender de un vistazo podría ser su mejor opción.

+5

La mayoría de los algoritmos de clasificación utilizan ciclos anidados o recursión y muchas comparaciones para ordenar un conjunto dado. Dependiendo de la cantidad de comparaciones que esté haciendo en esta parte crítica del código, las salidas anticipadas y la omisión de comparaciones innecesarias podrían generar un aumento significativo del rendimiento. –

+1

De acuerdo, buen punto, Yannick. – duffymo

+1

¿No sería útil también una legibilidad de if-else, así como dar al compilador una pista decente? –

3

else if sería más rápido en el sentido de que lo comparas hasta que llegues a una condición que se resuelva como verdadera, y te saltes el resto de las if s.

Considere también reordenar las comparaciones en orden de frecuencia descendente.

Y utilizando la instrucción switch según el tipo de datos del objeto que está comparando.

Sin embargo, en este punto, como ha sugerido Duffymo, estarías optimizando en micro. La ganancia de rendimiento nunca será tan significativa si no ha elegido primero el algoritmo de clasificación correcto para el trabajo.

7

Para ser sincero, no creo que importe la forma en que lo hagas en términos de rendimiento, dudo que veas alguna diferencia. Yo recomendaría el uso de una sentencia switch que no es un enhancment rendimiento, simplemente sintácticamente más agradable:

switch ($day) 
{ 
    case "Monday": 
     // do something with Monday 
     break; 
    case "Tuesday": 
     // do something with Tuesday 
     break; 
    case "Wednesday": 
     // do something with Wednesday 
     break; 
} 
+0

¡un interruptor es definitivamente una mejora de rendimiento en muchos casos! – Daniel

2

Si los valores son enteros, puede lograr una optimización utilizando una tabla de búsqueda. P.ej. Supongamos que tiene 256 valores que se mapean en 7 días de alguna manera, puede configurar una matriz con 256 celdas y cada celda contenía el día de la semana que deseaba.Entonces, en lugar de:


if (value == 0) { 
    dayofweek = 1; 
} else if (value == 1) { 
    dayofweek = 2; 
} else if (value == 2) { 
    dayofweek = 3; 
} else if ... 

.. usted podría tener ..


dayofweek = lookuparray[value]; 

Por supuesto, si se utiliza esta técnica, entonces usted debe comprobar los límites de valor primero.

0

En general, el estilo "else if" puede ser más rápido porque en la serie de ifs, cada condición se verifica una después de la otra; en una cadena "else if", una vez que se cumple una condición, el resto se pasa por alto.

El más rápido sería un despacho de tablas, que es en lo que se optimiza una sentencia switch cuando hay suficientes casos (si hay pocos casos en un switch, se traduce en una serie de verificaciones if-else en el código de máquina resultante).

0

La decisión de utilizar muchas sentencias if o if-elseif-elseif ... no debe basarse en el rendimiento, ya que esta decisión implica un flujo masivo de programas.

Dudo que pueda cambiar de muchas sentencias if a if-elseif grandes sin perder la funcionalidad.

Es una pregunta de diseño, no de rendimiento.

9

Puede echar un vistazo a phpbench

pero para ser honesto si desea optimizar a este nivel, es posible que desee aprender algo más que php.

alt text

0

me pondría otra votación en para optar por una sentencia switch() en su lugar.

2

Hice un punto de referencia si hay una verdadera diferencia entre los sucesivos si() y si() luego un poco elseif()

pongo una cadena grande e hicieron unos 20 strpos() cada vez (x100 000) con los dos métodos y mostró este resultado:

Try 1 : 0.5094 (including elseif) 
Try 2 : 0.6700 (including only if) 

No hay duda. Ya sabía que elsecessif() era más rápido, aunque hay un retorno en el medio; aún es bueno poner algunas estadísticas en la respuesta.

0

Esta pregunta es especialmente interesante cuando el bloque if regresa y finaliza así el método. También se aplica directamente a la forma en que funcionan los comparadores en Java.

He tanto ejecutar cada método (fuelle) 250.000.000 veces y los resultados son los siguientes:

two values if/else - 6.43 millis 
three values if/else/if - 8.66 millis 
three values if/if  - 9.01 millis 

Mientras que el peor de los casos tiene 1,4 veces más largo que el mejor hacer aviso de que se trata la suma total de iterar cada uno de estos métodos 250 millones de veces. Suponiendo que tomaría 100 ms para que un ser humano perciba la demora y que la diferencia peor/mejor sea de 2,58 millis, implicaría que necesitaría casi un billón (1000 * 1000 millones) de iteraciones para percibir la diferencia entre los diferentes métodos.

resumirlo: uso if-else es uno de esos casos en los que la opción más rápida es también el que más legibilidad y menos propenso a errores.

// methods used to measure difference between if and if/else 

/** equality is not important **/ 
private static int comparatorOfIfElse(int a, int b) { 
    if(a < b) return -1; 
    else return 1; 
} 

/** equality is taken into account using if/else **/ 
private static int comparatorOfIfElseIf(int a, int b) { 
    if(a < b) return -1; 
    else if(a > b) return 1; 
    return 0; 
} 

/** equality is taken into account using only if **/ 
private static int comparatorOfIf(int a, int b) { 
    if(a < b) return -1; 
    if(a > b) return 1; 
    return 0; 
} 
Cuestiones relacionadas