Great idea on interning a var at macro-time and then using it later! I did 
something similar for the ClojureScript implementation of inline caching 
but for some odd reason didn't think of doing it for the Clojure version. 
I'm seeing a big performance improvement for the [:a :b :c] benchmark from 
my post - about 15% faster than before and now very close to full manual 
precompilation.

Here's the 
commit: 
https://github.com/nathanmarz/specter/commit/fbca7ab99c84d93a28f7773f1c56be12e1a939a3


On Tuesday, May 31, 2016 at 9:33:29 PM UTC-4, puzzler wrote:
>
> I think this is an interesting problem, so here are some additional 
> brainstorms on the issue that may or may not be useful...
>
> One strategy to create a global mutable variable from inside the function 
> would be to use def at macroexpansion time to create a var, and then just 
> refer to it in the expansion, like this:
>
> (defmacro expand-to-something-with-mutable-global []
>   ; At macroexpansion time, create a (private) var containing a volatile.
>   (let [global-name (gensym "cache")]
>     (eval `(def ^:private ~global-name (volatile! nil)))    
>     ; Now macro can refer to this var, can use as a cache, etc.
>     `(if-let [cache-contents# (deref ~global-name)] 
>        (do-something-with cache-contents#)
>        (reset! ~global-name init-value-for-cache))))
>
> Not sure if this would be any faster than ConcurrentHashMap, but I would 
> guess that it would be if Clojure resolves the location of the var in 
> memory once, at compile-time.
>
> A related technique would be for Specter to maintain an ArrayList of 
> volatiles.  At macroexpansion time, you add a fresh volatile to the end of 
> the ArrayList, noting the index of its location, and then inside the macro 
> you hardcode a lookup in the ArrayList at the specific index to retrieve 
> the volatile containing the cache for this particular expansion.  I would 
> expect this to be faster than looking up in a hash map, although there'd be 
> some additional concurrency/locking details to worry about that I assume 
> ConcurrentHashMap handles for you.
>
> Or just use an ArrayList's slot directly as the cache (rather than storing 
> a volatile to add a level of indirection), but then the concurrency 
> logistics would be even more complicated.
>
> On Tue, May 31, 2016 at 12:50 PM, Nathan Marz <natha...@gmail.com 
> <javascript:>> wrote:
>
>> No, because that global mutable variable would need to be specifiable by 
>> Specter on usage of the library. For example, if you wrote:
>>
>> (defn foo []
>>   (select [:a :b] {:a {:b 1}}))
>>
>> `select` has no ability to control anything outside the context of its 
>> form. It certainly can't wrap `foo` to put a volatile field in its closure. 
>> So for the static-field idea, it would expand to something like:
>>
>> (defn foo []
>>   (static-field [pathcache]
>>      (if-not pathcache (set! pathcache ...))
>>      ...
>>      ))
>>
>>
>>
>> On Tuesday, May 31, 2016 at 3:15:26 PM UTC-4, puzzler wrote:
>>>
>>> In your writeup, you say that there would be further speed benefits if 
>>> you could have a global mutable variable within the context of a function 
>>> (like a static field).
>>>
>>> Can't you effectively accomplish that already in Clojure like this?:
>>>
>>> (let [mycache (volatile! nil)]
>>>   (defn foo []
>>>       ...)))
>>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to