World benchmarking is very often misleading, and generally quite difficult to fix. The easiest way to get reasonably close in clojure (which I found is the criteria library (thanks Hugo!). If I start with the ugly version of factorial computing with a simple loop, I get about 3 ns.
user> (defn loopy-fact [x] (loop [yx answer-so-far 1] (if (pos? y) (recur (dec y) (*' answer-so-far y)) answer-so-far))) #'user/loopy-fact user> (loopy-fact 100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000N
And then give an assessment:
user> (criterium.core/bench
If we then make the code better using the usual clojure style, with a map and reduce it, and donβt make any effort to quickly execute it.
user> (defn mapy-fact [x] (reduce *' (range 1 (inc x))) #'user/mapy-fact user> (mapy-fact 100) 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000N
Now let's find out how this compares:
user> (criterium.core/bench
This is a bit slower, but only slower by two nanoseconds .
This is much better than in your test, because the criterion runs the function enough time for the JVM Hotspot compiler to bypass its compilation and encrust all parts. This demonstrates why microobjects can be misleading to the JVM . and you will almost certainly adhere to the criteria for such cases.
PS: *'
is an opponent of the multiplication of "auto-promotion", he will contribute to its use for large or large decimal places as necessary
source share