mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-17 01:51:10 +00:00
[nop] Micro-optimize binding conveyance
Avoid repeatedly capturing the same callsite binding frame for each registered handler. While the perf benefit of this change is minimal, the approach is also conceptually cleaner.
This commit is contained in:
parent
8066776a80
commit
b4b06f324b
3 changed files with 35 additions and 19 deletions
|
|
@ -43,7 +43,10 @@
|
||||||
{:sf-arity 4
|
{:sf-arity 4
|
||||||
:ct-sig-filter impl/ct-sig-filter
|
:ct-sig-filter impl/ct-sig-filter
|
||||||
:*rt-sig-filter* impl/*rt-sig-filter*
|
:*rt-sig-filter* impl/*rt-sig-filter*
|
||||||
:*sig-handlers* impl/*sig-handlers*})
|
:*sig-handlers* impl/*sig-handlers*
|
||||||
|
:lib-dispatch-opts
|
||||||
|
(assoc sigs/default-handler-dispatch-opts
|
||||||
|
:convey-bindings? false)})
|
||||||
|
|
||||||
;;;; Aliases
|
;;;; Aliases
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,9 +279,11 @@
|
||||||
|
|
||||||
;;;; Handlers
|
;;;; Handlers
|
||||||
|
|
||||||
(enc/defonce ^:dynamic *sig-spy* "To support `with-signals`, etc." nil)
|
|
||||||
(enc/defonce ^:dynamic *sig-handlers* "?[<wrapped-handler-fn>]" nil)
|
(enc/defonce ^:dynamic *sig-handlers* "?[<wrapped-handler-fn>]" nil)
|
||||||
|
|
||||||
|
(defrecord SpyOpts [vol_ last-only? trap?])
|
||||||
|
(def ^:dynamic *sig-spy* "?SpyOpts" nil)
|
||||||
|
|
||||||
(defn force-msg-in-sig [sig]
|
(defn force-msg-in-sig [sig]
|
||||||
(if-not (map? sig)
|
(if-not (map? sig)
|
||||||
sig
|
sig
|
||||||
|
|
@ -309,7 +311,7 @@
|
||||||
([ trap-signals? form] `(with-signal false ~trap-signals? ~form))
|
([ trap-signals? form] `(with-signal false ~trap-signals? ~form))
|
||||||
([raw-msg? trap-signals? form]
|
([raw-msg? trap-signals? form]
|
||||||
`(let [sig_# (volatile! nil)]
|
`(let [sig_# (volatile! nil)]
|
||||||
(binding [*sig-spy* [sig_# :last-only ~trap-signals?]]
|
(binding [*sig-spy* (SpyOpts. sig_# true ~trap-signals?)]
|
||||||
(enc/try* ~form (catch :all _#)))
|
(enc/try* ~form (catch :all _#)))
|
||||||
|
|
||||||
(if ~raw-msg?
|
(if ~raw-msg?
|
||||||
|
|
@ -326,7 +328,7 @@
|
||||||
([raw-msgs? trap-signals? form]
|
([raw-msgs? trap-signals? form]
|
||||||
`(let [sigs_# (volatile! nil)
|
`(let [sigs_# (volatile! nil)
|
||||||
form-result#
|
form-result#
|
||||||
(binding [*sig-spy* [sigs_# (not :last-only) ~trap-signals?]]
|
(binding [*sig-spy* (SpyOpts. sigs_# false ~trap-signals?)]
|
||||||
(enc/try*
|
(enc/try*
|
||||||
(do [~form nil])
|
(do [~form nil])
|
||||||
(catch :all t# [nil t#])))
|
(catch :all t# [nil t#])))
|
||||||
|
|
@ -338,16 +340,23 @@
|
||||||
|
|
||||||
[form-result# (not-empty sigs#)]))))
|
[form-result# (not-empty sigs#)]))))
|
||||||
|
|
||||||
|
#?(:clj (def ^:dynamic *sig-spy-off-thread?* false))
|
||||||
(defn dispatch-signal!
|
(defn dispatch-signal!
|
||||||
"Dispatches given signal to registered handlers, supports `with-signal/s`."
|
"Dispatches given signal to registered handlers, supports `with-signal/s`."
|
||||||
[signal]
|
[signal]
|
||||||
(or
|
(or
|
||||||
(when-let [[v_ last-only? trap-signals?] *sig-spy*]
|
(when-let [{:keys [vol_ last-only? trap?]} *sig-spy*]
|
||||||
(let [sv (sigs/signal-value signal nil)]
|
(let [sv
|
||||||
|
#?(:cljs (sigs/signal-value signal nil)
|
||||||
|
:clj
|
||||||
|
(if *sig-spy-off-thread?* ; Simulate async handler
|
||||||
|
(deref (enc/promised :user (sigs/signal-value signal nil)))
|
||||||
|
(do (sigs/signal-value signal nil))))]
|
||||||
|
|
||||||
(if last-only?
|
(if last-only?
|
||||||
(vreset! v_ sv)
|
(vreset! vol_ sv)
|
||||||
(vswap! v_ #(conj (or % []) sv))))
|
(vswap! vol_ #(conj (or % []) sv))))
|
||||||
(when trap-signals? :stop))
|
(when trap? :stop))
|
||||||
|
|
||||||
(sigs/call-handlers! *sig-handlers* signal)))
|
(sigs/call-handlers! *sig-handlers* signal)))
|
||||||
|
|
||||||
|
|
@ -639,9 +648,9 @@
|
||||||
`(let [signal# ~record-form]
|
`(let [signal# ~record-form]
|
||||||
(reduce-kv assoc signal# (.-kvs signal#)))))]
|
(reduce-kv assoc signal# (.-kvs signal#)))))]
|
||||||
|
|
||||||
`(delay
|
`(enc/bound-delay
|
||||||
;; Delay (cache) shared by all handlers. Covers signal `:let` eval, signal construction,
|
;; Delay (cache) shared by all handlers, incl. `:let` eval,
|
||||||
;; middleware (possibly expensive), etc. Throws here will be caught by handler.
|
;; signal construction, middleware, etc. Throws caught by handler.
|
||||||
~do-form
|
~do-form
|
||||||
(let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc.
|
(let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc.
|
||||||
signal# ~signal-form]
|
signal# ~signal-form]
|
||||||
|
|
@ -721,7 +730,7 @@
|
||||||
~@into-let-form ; Inject conditional bindings
|
~@into-let-form ; Inject conditional bindings
|
||||||
signal# ~signal-delay-form]
|
signal# ~signal-delay-form]
|
||||||
|
|
||||||
(dispatch-signal! ; Runner preserves dynamic bindings when async.
|
(dispatch-signal!
|
||||||
;; Unconditionally send same wrapped signal to all handlers.
|
;; Unconditionally send same wrapped signal to all handlers.
|
||||||
;; Each handler will use wrapper for handler filtering,
|
;; Each handler will use wrapper for handler filtering,
|
||||||
;; unwrapping (realizing) only allowed signals.
|
;; unwrapping (realizing) only allowed signals.
|
||||||
|
|
|
||||||
|
|
@ -228,12 +228,16 @@
|
||||||
(is (= rv6 13)) (is (= (force (get sv6 dk)) [:n 12, :c6 15]))
|
(is (= rv6 13)) (is (= (force (get sv6 dk)) [:n 12, :c6 15]))
|
||||||
(is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")]))))
|
(is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")]))))
|
||||||
|
|
||||||
(testing "Binding conveyance"
|
(testing "Dynamic bindings, etc."
|
||||||
(binding [*dynamic-var* :foo]
|
[(binding[#?@(:clj [impl/*sig-spy-off-thread?* true])
|
||||||
(is (sm? (with-sig (sig! {:level :info, :data {:dynamic-var *dynamic-var*}})) {:data {:dynamic-var :foo}}))))
|
*dynamic-var* "foo"
|
||||||
|
tel/*ctx* "bar"]
|
||||||
|
(let [sv (with-sig (sig! {:level :info, :data {:*dynamic-var* *dynamic-var*, :*ctx* tel/*ctx*}}))]
|
||||||
|
(is (sm? sv {:data {:*dynamic-var* "foo", :*ctx* "bar"}})
|
||||||
|
"Retain dynamic bindings in place at time of signal call")))
|
||||||
|
|
||||||
(testing "Dynamic context (`*ctx*`)"
|
(let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))]
|
||||||
(let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt")))
|
(is (sm? sv {:ctx "my-ctx"}) "`*ctx*` can be overridden via call opt"))])
|
||||||
|
|
||||||
(testing "Dynamic middleware (`*middleware*`)"
|
(testing "Dynamic middleware (`*middleware*`)"
|
||||||
[(is (sm? (tel/with-middleware nil (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity")
|
[(is (sm? (tel/with-middleware nil (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue