> With repeated runs, and my cpu frequency set to not change, I get very
> little speed improvement. I increased the size of the example range
> times 10 for these runs:
For me there is a very clear speed improvement of at least 40%, doing
quite a lot of repeated runs. I can't run with range times 10 because
it crashes my REPL, so I guess it is quite machine/JVM specific as to
the relative performances. Here is a sample extract of how I tested
(more runs done in practice). I'm not sure how to "cpu frequency set
to not change" or how significant that is on my results.
;; first setting up the test and using normal get
user=> (defstruct desilu :fred :ricky)
#'user/desilu
user=> (def x (map (fn [n]
(struct-map desilu
:fred n
:ricky 2
:lucy 3
:ethel 4))
(range 100000)))
#'user/x
user=> (def fred (accessor desilu :fred))
#'user/fred
;; ignore the first one
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 1365.325055 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 91.447766 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 72.951146 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 78.106709 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 76.300491 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
"Elapsed time: 81.184388 msecs"
4999950000
;; switching to accessor, getting a consistent speed increase of about
40%
user=> (time (reduce (fn [n y] (+ n (fred y))) 0 x))
"Elapsed time: 53.602536 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (fred y))) 0 x))
"Elapsed time: 51.098607 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (fred y))) 0 x))
"Elapsed time: 51.512913 msecs"
4999950000
user=> (time (reduce (fn [n y] (+ n (fred y))) 0 x))
"Elapsed time: 53.062693 msecs"
4999950000
;; I defined my own access method so that an accessor is not required,
;; however then you need to type hint which makes it too clumsy
;; performs very similar to an accessor, in theory slightly faster
;;public Object access(int i) throws Exception{
;; return vals[i];
;;}
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 53.376319 msecs"
4999950000
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 49.545614 msecs"
4999950000
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 49.348831 msecs"
4999950000
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 49.313406 msecs"
4999950000
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 51.485216 msecs"
4999950000
user=> (time (reduce (fn [n #^clojure.lang.PersistentStructMap y] (+ n
(.access y 0))) 0 x))
"Elapsed time: 50.024856 msecs"
4999950000
;; then I try running with 10x as you suggested
user=> (defstruct desilu :fred :ricky)
#'user/desilu
user=> (def x (map (fn [n]
(struct-map desilu
:fred n
:ricky 2
:lucy 3
:ethel 4))
(range 1000000)))
#'user/x
user=> (time (reduce (fn [n y] (+ n (:fred y))) 0 x))
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown
Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at jline.ConsoleRunner.main(ConsoleRunner.java:69)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.lang.reflect.Method.copy(Unknown Source)
at java.lang.reflect.ReflectAccess.copyMethod(Unknown Source)
at sun.reflect.ReflectionFactory.copyMethod(Unknown Source)
at java.lang.Class.copyMethods(Unknown Source)
at java.lang.Class.getMethods(Unknown Source)
at clojure.lang.Reflector.getMethods(Reflector.java:300)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:
27)
at clojure.main$repl__5506$fn__5509.invoke(main.clj:136)
at clojure.main$repl__5506$fn__5524.invoke(main.clj:154)
at clojure.main$repl__5506.doInvoke(main.clj:145)
at clojure.lang.RestFn.invoke(RestFn.java:426)
at clojure.main$repl_opt__5548.invoke(main.clj:208)
at clojure.main$legacy_repl__5573.invoke(main.clj:249)
at clojure.lang.Var.invoke(Var.java:327)
at clojure.main.legacy_repl(main.java:29)
at clojure.lang.Repl.main(Repl.java:20)
... 5 more
;; REPL crashed