Al fine di impatto ipotizzata sui risultati relativi:
La funzione do-with
usa nth
per accedere alle singole voci nelle collezioni di ingresso. nth
opera in tempo lineare su intervalli, rendendo do-with
quadratica. Inutile dire che questo ucciderà le prestazioni su grandi collezioni.
range
produce seguenti del regolamento provvisorio divisi in blocchi e map
gestisce quelli estremamente efficiente. (Essenzialmente produce pezzi fino a 32 elementi - qui sarà infatti esattamente 32 - eseguendo un ciclo stretto sopra la matrice interna di ciascun blocco di ingresso, a sua volta, mettendo risultati in matrici interne dei blocchi di uscita.)
Benchmarking con time
non ti dà prestazioni steady state. (Che è il motivo per cui si dovrebbe davvero utilizzare una libreria di benchmarking corretta, nel caso di Clojure, Criterium è la soluzione standard.)
Per inciso, (map #(/ %1 %2) xs ys)
può semplicemente essere scritto come (map/xs ys)
.
Aggiornamento:
ho benchmark la versione map
, l'originale do-with
e una nuova versione do-with
con Criterium, utilizzando (range 1 1000)
come entrambi gli ingressi in ogni caso (come nel testo della domanda), ottenendo il seguente significare tempi di esecuzione:
;;; (range 1 1000)
new do-with 170.383334 µs
(doall (map ...)) 230.756753 µs
original do-with 15.624444 ms
Inoltre, ho ripetuto il benchmark utilizzando un vettore memorizzato in un Var come input anziché intervalli (cioè con (def r (vec (range 1 1000)))
al avviare d utilizzando come r
entrambi gli argomenti di raccolta in ogni benchmark). Non sorprende che l'originale do-with
è venuto in primo - nth
è molto veloce su vettori (più utilizzando nth
con un vettore evita tutte le allocazioni intermedi coinvolti nella ss attraversamento).
;;; (vec (range 1 1000))
original do-with 73.975419 µs
new do-with 87.399952 µs
(doall (map ...)) 153.493128 µs
Ecco il nuovo do-with
con la complessità tempo lineare:
(defn do-with [f xs ys]
(loop [xs (seq xs)
ys (seq ys)
ret (transient [])]
(if (and xs ys)
(recur (next xs)
(next ys)
(conj! ret (f (first xs) (first ys))))
(persistent! ret))))
fonte
2013-08-05 07:40:54
Grazie per la risposta dettagliata e ben arrotondati. Sembra che ho bisogno di essere più consapevole di quale tipo di operazione sto facendo su quale tipo di struttura dei dati. – Core