2013-01-17 13 views
5

Ho una condizione per controllare dire eliminare e articolo se l'utente è proprietario.se condizione vs &&, c'è qualche guadagno in termini di prestazioni

delete_article if user.owner? 

Un altro modo è

user.owner? && delete_article 

Quali sono i vantaggi nella scelta di uno di esso o è solo uno stile di scrittura

+10

prima è più chiaro in termini di intenzioni – apneadiving

+0

Scrivi un punto di riferimento e scoprilo da solo. È abbastanza facile da fare. –

+0

I vantaggi prestazionali come questo (se ce ne sono) non saranno significativi per un'app Web (la latenza di rete/I/O diminuirà i guadagni). Quindi punterei allo stile, personalmente preferisco 'if' a' && 'in questo caso. – Kris

risposta

2

Ecco alcuni codici per testare la velocità di if rispetto a &&.

require 'benchmark' 

n = 10_000_000 

puts RUBY_VERSION, n 
puts 

Benchmark.bm(2) do |b| 
    10.times do 
    b.report('if') { n.times { true if true } } 
    b.report('&&') { n.times { true && true } } 
    end 
end 

E l'output:

1.9.3 
10000000 

     user  system  total  real 
if 0.970000 0.000000 0.970000 ( 0.975714) 
&& 1.130000 0.000000 1.130000 ( 1.127514) 
if 0.950000 0.000000 0.950000 ( 0.956892) 
&& 1.120000 0.000000 1.120000 ( 1.124547) 
if 0.970000 0.000000 0.970000 ( 0.962618) 
&& 1.120000 0.000000 1.120000 ( 1.129094) 
if 0.960000 0.000000 0.960000 ( 0.954498) 
&& 1.120000 0.000000 1.120000 ( 1.125080) 
if 0.960000 0.000000 0.960000 ( 0.954001) 
&& 1.120000 0.000000 1.120000 ( 1.126329) 
if 0.950000 0.000000 0.950000 ( 0.953360) 
&& 1.130000 0.000000 1.130000 ( 1.122664) 
if 0.950000 0.000000 0.950000 ( 0.951391) 
&& 1.120000 0.010000 1.130000 ( 1.123455) 
if 0.980000 0.000000 0.980000 ( 0.977263) 
&& 1.120000 0.000000 1.120000 ( 1.126989) 
if 0.970000 0.000000 0.970000 ( 0.966264) 
&& 1.120000 0.000000 1.120000 ( 1.123184) 
if 0.960000 0.000000 0.960000 ( 0.956702) 
&& 1.120000 0.000000 1.120000 ( 1.124589) 
+0

ohh I see Se è migliore (anche se trascurabile) – Ross

+0

È trascurabile in un programma a una riga, ma, ridimensionato in un programma completo che esegue molti condizionali all'interno di cicli, potrebbe richiedere fino a minuti o più. Il vantaggio dei benchmark è che possiamo apprendere modi efficienti per fare le cose, eseguirle in modo coerente e ottenere le migliori prestazioni da quello che molti percepiscono come un linguaggio "lento". –

0

Credo che entrambi gli stili di scrittura di questo avranno le stesse prestazioni. Preferisco sempre la prima versione in quanto è più facile da leggere e sebbene sia considerata "hacky" e "hard-core", la seconda versione non è in realtà un'ottimizzazione.

MODIFICA: Ecco come eseguire un benchmarking. Sembra che entrambe le versioni funzionino in modo simile:

limit = 10**7 
time_val=Time.now;sum=0;(0..limit).each{|t| even?(t) && sum += t};puts Time.now - time_val 

time_val=Time.now;sum=0;(0..limit).each{|t| sum += t if even?(t)};puts Time.now - time_val 
+0

Utilizza il [Benchmark] di Ruby incorporato (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html). È facile da configurare e offre modi decenti per formattare l'output. –

6

Le prestazioni non saranno probabilmente un problema con questa affermazione.

Il primo è molto meglio: è più facile da leggere. Il tuo futuro sé e gli altri che lavoreranno al codice ti ringrazieranno per questo.

+0

Vedere il punto di riferimento sulla differenza di velocità. –

+0

Sì, non è un problema –

0

Dovrebbero avere le stesse prestazioni di come fanno la stessa cosa, o almeno una differenza trascurabile nelle prestazioni.

+0

Hai sbagliato. 'true && 1 # => 1' –

+2

Restituiscono risultati diversi solo quando il primo non è vero' 1 se false # => nil' e 'false && 1 # => false' –

+0

Hmm in realtà sì, il mio male. Questo è strano –

3

È possibile utilizzare entrambi gli stili ma ci sono alcune differenze nella logica.

utilizzato in una chiamata di metodo:

def something 
    delete_article if user.owner? 
end 

sarebbe tornare a prescindere dalle dichiarazioni delete_article il metodo o nil se l'utente non è il proprietario.

Con:

def something 
    user.owner? && delete_article 
end 

sarebbe tornare false se l'utente non è un proprietario. Se l'utente è un proprietario, restituirà qualsiasi metodo restituisca il metodo delete_article.

Le prestazioni dovrebbero essere più o meno le stesse.

+0

In entrambi i casi, il valore restituito valuterà come "falso" perché nil e falso sono equivalenti per "verità". –

+0

Vero, ma devi essere consapevole del tipo di valore che ti aspetti ... forse hai qualcosa come 'result.nil?'. In caso di 'false' come valore di ritorno, valuterebbe' false'. – spas

0

In termini di prestazioni, if è meglio, come mostra l'Uomo di Latta.Ma a volte, è necessario scrivere utilizzando && o and se si vuole fare un one-liner, come nel caso in cui la parte principale include una variabile non-esempio che deve essere definito nella condizione:

do_something_with(foo) if foo = something_that_comes_from_condition 

restituirà un errore, ma

(foo = something_that_comes_from_condition) && do_something_with(foo) 

o

foo = something_that_comes_from_condition and do_something_with(foo) 

non ha tale problema.

Problemi correlati