This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-02-13
Channels
- # adventofcode (4)
- # announcements (1)
- # babashka (7)
- # beginners (51)
- # calva (18)
- # cider (15)
- # clj-kondo (1)
- # cljsrn (6)
- # clojure (99)
- # clojure-dev (31)
- # clojure-europe (5)
- # clojure-france (2)
- # clojure-italy (3)
- # clojure-nl (14)
- # clojure-seattle (8)
- # clojure-spec (6)
- # clojure-uk (2)
- # clojurescript (23)
- # conjure (3)
- # css (6)
- # data-science (3)
- # datomic (19)
- # events (6)
- # fulcro (13)
- # graalvm (5)
- # honeysql (24)
- # inf-clojure (19)
- # music (10)
- # off-topic (28)
- # pathom (10)
- # rdf (15)
- # re-frame (11)
- # releases (4)
- # sci (1)
- # shadow-cljs (18)
Is there an issue about that the defrecord's function ->Record
does not have :tag meta, so you need to use type hinting to access record fields using dot notation (like (.field ^Record (->Record ...))
)?
not sure, but FYI accesses to a record's fields have an inline optimization, so you can do (:foo r)
and it should be just as fast as a type-hinted (.-foo ^Record r)
That sounds very familiar -- I swear that's come up recently... gimme a sec...
https://ask.clojure.org/index.php/9168/defrecord-could-type-hint-the-record-constructor-functions
(no Jira ticket -- Alex is looking for a compelling example)
Thank you @seancorfield
@ghadi I am measuring something wrong here?
user=> (defrecord Foo [x])
user.Foo
user=> (let [^Foo r (->Foo 1)] (time (dotimes [i 1000000000] (.-x r))))
"Elapsed time: 260.812401 msecs"
nil
user=> (let [^Foo r (->Foo 1)] (time (dotimes [i 1000000000] (:x r))))
"Elapsed time: 2370.017491 msecs"
nil
(do
(let [x (->Foo 1)] (time (dotimes [_ 1000000] (.a x))))
(let [x (->Foo 1)] (time (dotimes [_ 1000000] (.a ^Foo x))))
(let [x (Foo. 1)] (time (dotimes [_ 1000000] (.a x))))
(let [x (Foo. 1)] (time (dotimes [_ 1000000] (:a x)))))
"Elapsed time: 1895.1031 msecs"
"Elapsed time: 3.8925 msecs"
"Elapsed time: 4.4709 msecs"
"Elapsed time: 11.5897 msecs"
The first usage just shows that reflection in a loop is slow. The other examples need more loops to be able to compare better.
user=> (defn kwaccess [v] (:x v))
#'user/kwaccess
user=> (defn getaccess [v] (get v :x))
#'user/getaccess
user=> (let [r (->Foo 1)] (time (dotimes [i 1000000000] (kwaccess r))))
"Elapsed time: 2810.895121 msecs"
nil
user=> (let [r (->Foo 1)] (time (dotimes [i 1000000000] (getaccess r))))
"Elapsed time: 8820.251502 msecs"
which makes sense probably since invoking a keyword is invoking a function which is another indirection
user=> (let [^Foo r (->Foo 1)] (time (dotimes [i 1000000000] (.-x r))))
"Elapsed time: 565.111442 msecs"
nil
user=> (let [^Foo r (->Foo 1)] (time (dotimes [i 1000000000] (:x r))))
"Elapsed time: 2362.38707 msecs"
nil
user=> (let [^Foo r (->Foo 1)] (time (dotimes [i 1000000000] (get r :x))))
"Elapsed time: 12014.947945 msecs"