This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-10
Channels
- # announcements (16)
- # aws (1)
- # babashka (2)
- # beginners (33)
- # biff (2)
- # clj-kondo (13)
- # cljs-dev (1)
- # cljsrn (3)
- # clojars (6)
- # clojure (198)
- # clojure-australia (3)
- # clojure-europe (41)
- # clojure-france (3)
- # clojure-nl (2)
- # clojure-spec (7)
- # clojure-uk (12)
- # clojurescript (57)
- # clojureverse-ops (1)
- # code-reviews (3)
- # community-development (2)
- # conjure (10)
- # data-science (1)
- # datomic (15)
- # depstar (2)
- # docker (2)
- # etaoin (1)
- # events (1)
- # exercism (5)
- # fulcro (23)
- # helix (23)
- # introduce-yourself (4)
- # jobs (6)
- # kaocha (1)
- # lsp (11)
- # meander (107)
- # off-topic (8)
- # pathom (3)
- # polylith (33)
- # re-frame (23)
- # reagent (7)
- # reitit (28)
- # remote-jobs (3)
- # sci (1)
- # shadow-cljs (2)
- # specter (5)
- # sql (38)
- # tools-deps (72)
- # web-security (9)
- # xtdb (32)
Weeeee, two performance PRs in ring merged 🎉 https://github.com/ring-clojure/ring/pull/446 https://github.com/ring-clojure/ring-codec/pull/34 Hopefully they'll be able to make it into reitit soon
https://github.com/ring-clojure/ring-codec/pull/34/files#diff-e42d7d4760cc0ec1368c75ec5ec79429d64d6795c32717c6576540162ceffc9aR145-R147 I remember @U064X3EF3 talked once that devs shouldn’t use MapEntry directly. I’m curious - why it is used here? Does it give performance boost in comparison with returning a list of two items for example?
Yes. Faster than both a list and a vector. You wouldn't care about it unless you were doing over 10k qps
It's sometimes hard to know what can and can't be used from the core. I expect MapEntry is used in more than one library out there
I found it - https://groups.google.com/g/clojure/c/FVcrbHJpCW4/m/Fh7NsX_Yb7sJ maybe it is already not relevant because it is from 2008.
(defrecord Pair [k v])
(defn- split-key-value-pair [^String s]
(let [i (.indexOf s #=(int \=))]
(cond
(pos? i) (->Pair (.substring s 0 i) (.substring s (inc i)))
(zero? i) (->Pair "" (.substring s (inc i)))
:else (->Pair s ""))))
I tried to use defrecord and here is my benchmarks:
# MapEntry
Evaluation count : 22697706 in 6 samples of 3782951 calls.
Execution time mean : 25.380441 ns
Execution time std-deviation : 6.288547 ns
Execution time lower quantile : 19.789665 ns ( 2.5%)
Execution time upper quantile : 32.343785 ns (97.5%)
Overhead used : 7.251431 ns
# Pair
Evaluation count : 19948320 in 6 samples of 3324720 calls.
Execution time mean : 25.188445 ns
Execution time std-deviation : 3.066662 ns
Execution time lower quantile : 21.601103 ns ( 2.5%)
Execution time upper quantile : 28.464897 ns (97.5%)
Overhead used : 7.251431 ns
Yes, here is how I got the results:
(defn test-1 [^String s]
(let [kv (split-key-value-pair-map-entry s)]
[(key kv) (val kv)]))
(defn test-2 [^String s]
(let [kv (split-key-value-pair-defrecord s)]
[(:k kv) (:v kv)]))
(quick-bench
(test-1 "foo=42"))
(quick-bench
(test-2 "foo=42"))
Again, I expect no significant difference for map entry and record, you'll see those with list and vector Maybe you'll see a difference with map entry if you direct link
The main difference is that MapEntry exists in Clojure and can be destructured like a user will expect. We don't have tuple or nominal tuple types, MapEntry lets me fake one instead of defining a bespoke one. Maybe it's my bias but I see introducing a new type as having a higher "pass" threshold than introducing a new function.
yeah, fair point
Thank you all. I'll update a new round of results in stress-server tomorrow morning and will rerun when these get merged. Really curious to see how much can be gained
sure, malli could also be a multi-module project. I don't have time to migrate, but help most welcome :)
Not sure it's possible https://clojurians.slack.com/archives/C6QH853H8/p1631264065169400?thread_ts=1631264065.169400&cid=C6QH853H8
Hi, I am trying to coerce data using the spec-tools, but it seems working not the way as I expected:
(require '[spec-tools.core :as st])
(s/def ::double double?)
(s/def ::x (s/keys :req-un [::double]))
(st/coerce ::x {:double 100} nil)
My expectation that double
will become 100.0
, but it is not the case atm
Are my expectations correct? Or what I am doing wrong?
thanks!@kirill.salykin I would guess having a nil
transformer means "do nothing". Also, not sure if JSON/string transformers in spec-tools have mapping from numbers to double, but should be easy to add, also in user side. Pretty sure that malli has those.
So coercion works works from the json/string representation only? No way to coerce clojure into clojure?
you can do any kind of x->edn->x transformations, transformers are both easy to compose and extend. There just isn't a edn->edn transformer pre-packaged, so you have to build one yourself. PR welcome. Here the list of current transformers: https://github.com/metosin/spec-tools/blob/master/src/spec_tools/core.cljc#L81-L176
Actually it think strip-* might work for me
Thanks
Hello, I'd like to ask whether the Dev workflow
approach described at https://cljdoc.org/d/metosin/reitit-ring/0.5.0-SNAPSHOT/doc/advanced/dev-workflow also applies to reitit.ring/router
. Basically I have a reitit ring router with some routes and I want the changes to routes to be refreshed automatically when I save/evaluate the changed definition. Currently I have to issue an integrant system reset which in turn stops and starts new instance of httpkit server with changed routes. This works fine, but I believe shouldn't be necessary. Any hints welcome 🤞.