Fork me on GitHub
#malli
<
2021-07-02
>
rmcv07:07:45

How do I provide sci options in malli decode? Trying to use java class with no luck.

(m/decode [:int {:decode/string '(fn [_] (.toEpochMilli (java.time.Instant/now)))}]

          "whatever"

          {:classes {'java.time.Instant java.time.Instant}}

          mt/string-transformer)

ikitommi09:07:00

looking at the code, it’s :malli.core/sci-options key in options, see https://github.com/metosin/malli/blob/master/src/malli/core.cljc#L1792-L1813

rmcv14:07:11

tried this

(m/decode [:int {:decode/string '(fn [_] (.toEpochMilli (java.time.Instant/now)))}]
          "whatever"
          (merge
           (m/-default-sci-options)
           {:malli.core/sci-options {:classes {'java.time.Instant java.time.Instant}}})
          mt/string-transformer)

ikitommi09:07:41

@ben.sless merged the loop unrolling perf PR, great for common cases and as it’s just clj, doesn’t make the cljs bundle size any bigger, big thanks!

;; 164ns -> 36ns
(let [valid? (m/validator [:and [:> 0] [:> 1] [:> 2] [:> 3] [:> 4]])]
  (cc/quick-bench (valid? 5)))

🎉 11
👍 8
ikitommi10:07:55

merged the other perf PR too:

;; 150ns -> 39ns
(let [valid? (m/validator [:map [:a :any] [:b :any] [:c :any] [:d :any] [:e :any]])
      value {:a 1, :b 2, :c 3, :d 4, :e 5}]
  (cc/with-progress-reporting
    (cc/quick-bench (valid? value))))

clojure-spin 4
🎉 9
Richard Hundt09:07:04

@U055NJ5CC I've created https://github.com/metosin/malli/issues/472 with a test case which demonstrates the issue.

Ben Sless11:07:07

@U026F3GM8NA I profiled you example, it looks like CPU mostly goes towards parsing the schema. If you wrap every def-ed schema with a schema constructor it seems to be way more efficient, would you mind trying?

Richard Hundt11:07:26

D'you mean just wrapping it in a function which returns the structure? (I'm not sure what you mean by "schema constructor")

Ben Sless11:07:25

like so;

(def A1
  (m/schema
   [:map
    {:encode/test {:leave encode} :decode/test decode}
    [:type [:= "A1"]]
    [:value float?]
    ]))

Richard Hundt11:07:44

thanks, I'll try

Ben Sless11:07:44

m/schema parses the children once

Ben Sless11:07:57

your implementation has no way to cache these results

Ben Sless11:07:31

It's a bother to do from scratch, you can take this

Ben Sless11:07:06

thanks slack, very helpful

Ben Sless11:07:02

there, more convenient

Richard Hundt11:07:38

yeah, that's pretty much instant now, I'll try it on our production code

Richard Hundt11:07:05

Perfect. Thanks Ben! What shall I do with the github issue? Do I close it, or are you planning on making changes to parsing?

ikitommi12:07:28

I closed the issue, no plans on making the parser faster or caching at the moment. Thanks for @ben.sless for digging into this 🙇

Ben Sless12:07:06

I think it is worth to leave a comment on the issue and perhaps a note in the readme regarding references to uncompiled schemas

Ben Sless12:07:50

And you're welcome 🙂 Turns out I was completely wrong regarding the transformers and satisfies?

Ben Sless12:07:57

I see you left a comment with a link to the gist, so that would leave only the readme

ikitommi13:07:13

if you have idea what and where to write this, please do 🙂

👍 3
ikitommi10:07:05

@ben.sless, great work. Saw the thread on Clojureverse about compiler optimizations. Would be great if things got automatically or magically faster. While waiting, writing performant code inside the libraries (on the hot perf path) is just being smart.

🙏 4
4
Ben Sless11:07:35

Thank you, I appreciate it. Blame it all on the talk you gave on ClojureTRE 2019