2009-11-25 11 views
18

Sto iterando attraverso un array e ordinandolo per valori in giorni della settimana.Cosa è più veloce: molti ifs, altrimenti se?

Per farlo, sto utilizzando molte istruzioni if. Fa qualche differenza con la velocità di elaborazione se utilizzo più if s, rispetto a un set di istruzioni else if?

+1

Non conosco la velocità di elaborazione, ma se ne hai così tanti se blocchi, forse dovresti prendere in considerazione l'utilizzo di un'istruzione switch. Soprattutto per qualcosa come i giorni di una settimana. –

+0

C'è un enorme cambiamento di funzione quando si passa da molte istruzioni if ​​a una istruzione if-elseif. Pensa a cosa fa realmente il tuo codice. –

risposta

41

Sì, utilizzare un altro caso, si consideri il seguente codice:

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

di

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

nel secondo caso se predicatoA è vero, il predicatoB (e qualsiasi altro predicato) non dovrà essere valutato (e quindi l'intero codice verrà eseguito più velocemente), mentre nel primo esempio se predicatoA è t rue, predicateB sarà sempre valutato, e potresti anche avere delle sorprese inaspettate se predicatoA e predicatoB non si escludono a vicenda.

+1

Dovrebbe essere una quantità notevole di condizioni per vedere effettivamente una differenza di prestazioni, tuttavia +1 come se altrimenti sarebbe il modo corretto comunque. – James

+5

In realtà, il tuo esempio è sbagliato, perché non faranno lo stesso se sia PredicateA che PredicateB possono ocurre. eseguirai solo il primo e uscirai. mentre il primo codice eseguirà entrambi. –

17

Dubito che una micro ottimizzazione come questa farà una differenza misurabile nel codice.

L'algoritmo di ordinamento è più probabile che sia la fonte di un problema di prestazioni. Quale algoritmo di scelta sceglierai sarà critico, non molti "se" o "altro se".

UPDATE:

I punti fatti da altri su "else if" essere una scelta migliore, a causa della sua uscita anticipata e le caratteristiche logiche esclusive, suggeriscono che dovrebbe essere preferito "se" in questo caso.

Ma il punto sulla scelta dell'algoritmo rimane valido, a meno che il set di dati non sia molto piccolo.

È ovvio che O (log n) sarebbe migliore di O (n^2), ma anche la dimensione del set di dati è importante. Se hai solo pochi elementi, potresti non notare la differenza. In tal caso, la codifica di un metodo inefficiente nel modo più pulito, leggibile e facilmente comprensibile a colpo d'occhio potrebbe essere la soluzione migliore.

+5

La maggior parte degli algoritmi di ordinamento utilizza cicli nidificati o ricorsione e molti confronti per ordinare un determinato set. A seconda del numero di confronti che sta facendo in questa parte critica del codice, i primi ritardi e l'eliminazione dei confronti non necessari potrebbero comportare un significativo aumento delle prestazioni. –

+1

Concordato, buon punto, Yannick. – duffymo

+1

Non sarebbe utile anche una leggibilità dell'aiuto if, oltre a dare al compilatore un suggerimento decente? –

3

else if sarebbe più veloce nel senso che si confronta fino a quando non si preme una condizione che si risolve in true, e si salta il resto del if s.

Considerare inoltre di riordinare i confronti in ordine di frequenza decrescente.

E utilizzando l'istruzione switch in base al tipo di dati dell'oggetto che si sta confrontando.

Tuttavia, a questo punto, come suggerito da duffymo, si sarebbe ottimizzato il microscopio. Il guadagno in termini di prestazioni non sarà mai così significativo se non si è scelto prima l'algoritmo di ordinamento corretto per il lavoro.

7

Per essere onesto, non credo che sarebbe importante in che modo lo si fa in termini di prestazioni, dubito che vedreste alcuna differenza. Ti consiglio di utilizzare un'istruzione switch che non è un enhancment prestazioni, semplicemente sintatticamente più bello:

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 interruttore è sicuramente un miglioramento delle prestazioni su molti se! – Daniel

2

Se i valori sono numeri interi, è possibile ottenere un'ottimizzazione utilizzando una ricerca tabella. Per esempio. Supponiamo che tu abbia 256 valori mappati in 7 giorni in qualche modo, potresti configurare un array con 256 celle e ogni cella conteneva il giorno della settimana desiderato.Poi, invece di:


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

.. si potrebbe avere ..


dayofweek = lookuparray[value]; 

Naturalmente, se si utilizza questa tecnica, allora si dovrebbe verificare i limiti di valore prima.

0

In generale, lo stile "else if" può essere più veloce perché nella serie di ifs, ciascuna condizione viene controllata una dopo l'altra; in una catena "else if", una volta soddisfatta una condizione, il resto viene bypassato.

Il più veloce sarebbe un dispatch di tabella, che è ciò che viene ottimizzato in una dichiarazione di switch quando ci sono abbastanza casi in esso (se ci sono pochi casi in un interruttore, viene tradotto in una serie di controlli if-else in il codice macchina risultante).

0

La decisione di utilizzare molte istruzioni if ​​o una if-elseif-elseif non deve basarsi sulle prestazioni, poiché questa decisione coinvolge il flusso del programma in maniera massiccia.

Dubito che sia possibile passare da molte istruzioni if ​​ad un grande if-else senza perdere funzionalità.

È una domanda di design, non una performance.

9

Si può avere uno sguardo al phpbench

ma ad essere onesti se si desidera ottimizzare a questo livello, si potrebbe desiderare di imparare qualcosa di diverso php.

alt text

0

vorrei mettere un altro voto per la scelta di un'istruzione switch(), invece.

2

Ho fatto un punto di riferimento se c'è una vera differenza tra successivi se() e se(), poi un paio di elseif()

ho messo un grande corda e fatto circa 20 strpos() ogni volta (x100 000) con i due metodi e ha mostrato questo risultato:

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

Non c'è dubbio. Sapevo già che i sucessivi elseif() erano più veloci, anche se c'è un ritorno nel mezzo; è ancora bello inserire alcune statistiche nella risposta.

0

Questa domanda è particolarmente interessante quando il blocco if restituisce terminando così il metodo. Si applica anche direttamente al modo in cui i comparatori in Java funzionano.

Ho quindi eseguire ciascun metodo (sotto) 250.000.000 volte ei risultati sono i seguenti:

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

Mentre il caso peggiore prende 1,4 volte più lungo di quello migliore farlo notare che questo è la somma totale di iterare ciascuno di questi metodi 250 milioni di volte. Supponendo che ci vorrebbe 100ms per un ritardo percepito dall'uomo e che la differenza peggiore/migliore è di 2,58 millis implicherebbe che avresti bisogno di quasi mille miliardi di iterazioni per percepire la differenza tra diversi metodi.

Riassumendo in su: uso if-else è uno di quei casi in cui l'opzione più veloce è anche quella con più leggibilità e meno soggetto a errori.

// 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; 
} 
Problemi correlati