Quello che potrebbe essere un effetto trascurabile in un'applicazione completa del mondo reale diventa non trascurabile quando si scrivono one-liner che dipendono dal tempo in precedenza "trascurabili". Ho il sospetto che se il profilo i test allora la maggior parte del tempo sarà nella clausola summarize
, così lascia microbenchmark qualcosa di simile a quello:
> set.seed(99);z=sample(10000,4,TRUE)
> microbenchmark(z %>% unique %>% list, list(unique(z)))
Unit: microseconds
expr min lq mean median uq max neval
z %>% unique %>% list 142.617 144.433 148.06515 145.0265 145.969 297.735 100
list(unique(z)) 9.289 9.988 10.85705 10.5820 11.804 12.642 100
Questo sta facendo qualcosa di un po 'diverso per il codice, ma illustra il punto. I tubi sono più lenti.
Poiché le tubature devono ristrutturare la chiamata di R nella stessa che le valutazioni di funzione stanno utilizzando e quindi valutarle. Quindi lo ha lo più lento. Da quanto dipende da quanto siano veloci le funzioni. Le chiamate a unique
e list
sono piuttosto veloci in R, quindi l'intera differenza qui è il sovraccarico del tubo.
profilatura espressioni come questo mi ha mostrato la maggior parte del tempo viene speso nelle funzioni di tubo:
total.time total.pct self.time self.pct
"microbenchmark" 16.84 98.71 1.22 7.15
"%>%" 15.50 90.86 1.22 7.15
"eval" 5.72 33.53 1.18 6.92
"split_chain" 5.60 32.83 1.92 11.25
"lapply" 5.00 29.31 0.62 3.63
"FUN" 4.30 25.21 0.24 1.41
..... stuff .....
poi da qualche parte intorno al 15 ° posto il lavoro vero viene fatto:
"as.list" 1.40 8.13 0.66 3.83
"unique" 1.38 8.01 0.88 5.11
"rev" 1.26 7.32 0.90 5.23
Considerando che, se chiamate semplicemente le funzioni come intendevano le camere, R le raggiunge direttamente:
total.time total.pct self.time self.pct
"microbenchmark" 2.30 96.64 1.04 43.70
"unique" 1.12 47.06 0.38 15.97
"unique.default" 0.74 31.09 0.64 26.89
"is.factor" 0.10 4.20 0.10 4.20
Da qui la raccomandazione spesso citata che le pipe vanno bene sulla riga di comando dove il cervello pensa in catene, ma non in funzioni che potrebbero essere time-critical. In pratica questo overhead sarà probabilmente spazzato via in una chiamata allo glm
con poche centinaia di punti dati, ma questa è un'altra storia ....
Non si dovrebbero lasciare le unità. In questo caso, probabilmente stai parlando di millisecondi o anche di microsecondi. –
Se stai cercando di confrontare due snippet, eseguili entrambi nella stessa chiamata 'microbenchmark':' microbenchmark (code1 = {... primo snippet ...}, code2 = {... secondo snippet ...}) '(o senza i nomi) in modo da poter confrontare direttamente i tempi. – alistaire