> > I remain convinced that the solution is better compile-time inference: if > the compiler can infer that a var is never used dynamically, why should we > pay the overhead for extra indirection / dynamic features?
The answer to this appears to be the REPL - if the compiler goes ahead and infers this, then you can never change it in the REPL. If you update a function in the REPL which is used elsewhere (say in a map or filter) then you'd also have to transitively recompile all those cases. I do think there's scope for a production-mode compile. In this mode the compiler could optimise more aggressively and could also cache IFns instead of Vars, which would allow Hotspot to inline and generally optimise function calls but you'd lose the dynamic nature of Clojure somewhat. It's a slippery slope from there to whole-program optimisation, which might be an option for production deployments too. On 10 July 2013 19:40, Mikera <mike.r.anderson...@gmail.com> wrote: > Hi Colin, > > with-local-vars sadly doesn't actually create local variables on the stack > - it creates regular Clojure vars. Which is great for many uses, but they > still come with performance overhead (extra level of indirection, boxing > etc.). You need the compiler to actually produce the right low-level JVM > bytecode if you want these things to go fast for low-level code. > > Agree with you of course that it would be great if the compiler knew how > to optimise these cases. I remain convinced that the solution is better > compile-time inference: if the compiler can infer that a var is never used > dynamically, why should we pay the overhead for extra indirection / dynamic > features? The same goes for things like boxing and type casts. > > On Wednesday, 10 July 2013 01:15:14 UTC+1, Colin Fleming wrote: > >> Hi Mikera, >> >> For your mutable var loop example, I think with-local-vars should do what >> you want. >> >> It would be fantastic if the Clojure compiler could optimise these cases >> better, especially common higher-order use cases (like stream fusion). >> Unfortunately what always seems to kill the possibility is the fact that >> functions calls have to be indirected through vars. In the end those that >> want more performance will always have to sacrifice a little dynamicity >> (dynamicness? dynamism?) it seems. >> >> Cheers, >> Colin >> >> >> On 10 July 2013 05:28, Mikera <mike.r.an...@gmail.com> wrote: >> >>> On Tuesday, 9 July 2013 17:31:21 UTC+1, puzzler wrote: >>> >>> On Tue, Jul 9, 2013 at 8:11 AM, Alexander Gunnarson < >>>> alexander...@gmail.com> wrote: >>>> >>>>> My idea, which is probably very naive, but one which I'm curious >>>>> about, is: >>>>> >>>>> *Is it possible to have some sort of set of automatic-optimizing macros >>>>> that work on Clojure code to preserve elegance while maximizing >>>>> performance?* >>>>> >>>>> * >>>>> * >>>>> >>>>> In theory, it would be kind of an abstraction layer. There would be one >>>>> file that would store the code that gets read and another output file >>>>> that stores the code that actually gets evaluated by the REPL, and a set >>>>> of macros to optimize the "front-end", "abstracted" file into the output, >>>>> "nuts-and-bolts" file to be evaluated by the REPL. Probably this would be >>>>> a very intensive process - I don't know. But maybe it's worth the trouble >>>>> after all to save a ton of programmer-hours by increasing readability. >>>>> >>>>> >>>>> >>>> I think you're probably underestimating the scope of what the Clojure >>>> compiler already does. Arguably, it already is an auto-optimizing process >>>> that works on Clojure code to preserve elegance while maximing performance. >>>> >>> >>> The Clojure Compiler is fine, but it doesn't really do much in the way >>> of optimisation yet. >>> >>> It mainly just emits bog-standard bytecode corresponding to the >>> (macro-expanded) Clojure source. The good news is that the JVM JIT is >>> exceptionally good at micro-optimisation and this still results in pretty >>> decent performance. The bad news is that we are missing a lot of >>> opportunities to do optimisations that the JVM JIT can't possibly do >>> (because it doesn't know anything about the higher level structure and >>> assumptions in the code). >>> >>> I think we should aspire to improve the compiler further: we should >>> encourage ideas and discussions about how to improve it. >>> >>> I'd personally love to see Clojure match Java/Scala in performance for >>> idiomatic code, but we are still currently some way off. >>> >>> >>>> >>>> For the most part, Clojure programmers seem to be satisfied with >>>> dropping down to Java when the Clojure code gets too low-level to be >>>> elegant (although I think many would disagree that your examples have >>>> reached the level of inelegance). Still, there's probably room for >>>> something that targets the performance gap between Clojure and Java. >>>> >>>> I'm interested in an assembly-like DSL that could be easily interwoven >>>> with Clojure code, something like: >>>> http://www.rebol.com/docs/**rebc**ode.html<http://www.rebol.com/docs/rebcode.html> >>>> >>>> Zach Tellman recently released a library that does something like that: >>>> https://github.com/ztellman/**pr**imitive-math<https://github.com/ztellman/primitive-math> >>>> >>>> So far, the vast majority of Clojure performance improvements have >>>> focused on making it easier to work with primitive numbers (in loops and as >>>> function inputs), because Java's boxed numerics is what usually kills >>>> performance. I've only found these improvements marginally useful because >>>> I find that most numbers eventually end up in a Clojure data structure, >>>> where they become boxed. >>>> >>> >>> That's one of the reasons why we are building core.matrix :-) >>> >>> >>>> >>>> For me, the most useful thing would be an ability to drop down and do >>>> fast pointer manipulation and other mutable work, without having to go all >>>> the way to Java. >>>> >>> >>> Yeah, I've always wanted this too. Especially for mutable local counters >>> / accumulators. I'd love to be able to do something like: >>> >>> (let [^:mutable a 0 , ^:mutable b 0] >>> (dotimes [i 1000] >>> (set! a (+ a (foo i))) >>> (set! b (+ b (bar i)))) >>> ... more stuff with a and b....) >>> >>> This should compile down to something that performs the same as the >>> equivalent loop in Java. >>> >>> Of course, it would be even better if the following could compile down >>> to the same optimised loop: >>> >>> (reduce (fn [[a b] i] [(+ a (foo i)) (+ b (bar i))]) [0 0] (range 1000)) >>> >>> But currently..... the Clojure reduce version is around 20-50x slower >>> vs. equivalent Java code. >>> >>> >>>> >>>> Going in the other direction, I'd be interested in mechanisms that made >>>> it easier to write recursive code without having to worry about stack >>>> overflow. >>>> >>>> >>> A reasonably simple optimisation would be to automatically identify >>> self-recursion in tail position and convert it directly to "recur". I think >>> that's possibly the kind of optimisation pass that the OP was suggesting. >>> >>> -- >>> -- >>> 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 >>> >>> 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 >>> >>> For more options, visit this group at >>> http://groups.google.com/**group/clojure?hl=en<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. >>> >>> For more options, visit >>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>> . >>> >>> >>> >> >> -- > -- > 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/groups/opt_out. > > > -- -- 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/groups/opt_out.