Interesting....

在 2012年3月4日星期日UTC+8上午8时56分56秒,Mikhail Kryshen写道:
>
> If I understand Clojure's dynamic vars correctly, in a context where some
> var *bar* is already thread-bound, the following code:
>
>  (binding [*bar* new-val]
>    (foo))
>
> is semantically equivalent to:
>
>  (let [old-val *bar*]
>    (set! *bar* new-val)
>    (try
>      (foo)
>      (finally
>        (set! *bar* old-val))))
>
> The latter version appears to be 3 to 4 times faster if (foo) does nothing.
>
> The binding macro in the first version expands to something like:
>
>  (push-thread-bindings (hash-map (var *bar*) new-val))
>  (try
>    (foo)
>    (finally (pop-thread-bindings)))
>
> So the binding macro uses some stack implementation instead of just
> remembering the old value on the JVM call stack like the faster version
> does. I am probably missing something, but why do dynamic vars need to
> have their own stack for bindings?
>
> Also I noticed that replacing "(hash-map (var *bar*) new-val)" with
> "{(var *bar*) new-val}" in the above macro expansion makes it about 1.5-2
> times faster. This could also be fixed in the source of the binding
> defmacro by changing the following line:
>
>  (push-thread-bindings (hash-map ~@(var-ize bindings)))
>
> to:
>
>  (push-thread-bindings ~(apply hash-map (var-ize bindings)))
>
> --
> Mikhail
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to