On Sat, Aug 27, 2011 at 8:31 PM, Tal Liron <tal.li...@gmail.com> wrote:

> I can think of a few ways in which it would be possible to distribute a
> clojure.jar that supports JVM 7 features while still falling back to JVM 5
> compatibility. So, I don't think this was ever a barrier. But you obviously
> unconvinced by my report! Thank you for challenging me on this, As I said,
> I'm by no means 100% sure I exhausted the issue. I would encourage you to
> try out your ideas.
>

I agree. I wasn't saying that it was impossible to target both Java 5 and
take advantage of Java 7 features. I had mentioned that targeting Java 7
could be specified as an option when AOT compiling, or it could
automatically be detected when compiling at runtime. However, I think that
people (perhaps rightly so) make the argument that the amount of effort
weighed against compatibility concerns and resource allocation and the
percentage of Clojure code that would benefit, doesn't make it worth doing.
That's different than saying that there would be no benefit to Clojure.

*-- If you don't provide any type hints, then the constructor for
> InstanceMethodExpr sets method = null and warns you that you're doing
> reflection...[snip]
> *
> You are right! This is perhaps the only place where invokedynamic can be
> useful for Clojure. *However*, to me this is not a big deal, because the
> workaround of allowing for type hinting solves the problem just as well, and
> perhaps even more efficiently from the compiler's point of view. All it does
> is require some extra annotations by the programmer. The fact that Clojure
> emits a warning seems good enough for me, personally.
>

This seems to be a standard response from people, and I don't really
understand it. You are comparing apples to oranges. Don't get me wrong. Type
hints are a critical tool for improving the performance of critical
sections, and would probably be necessary even if Clojure's dynamic dispatch
was faster than it is, but it seems like a win to just automatically make
dispatch faster without type hints, and I guess it boils down to mostly
non-technical factors (see above). Plus the biggest boost would be to code
that interoperates with Java, which is arguably rarer than pure Clojure code
(though I think that invokedynamic could even speed up Var dispatch,
protocol dispatch, and multimethod dispatch (see below)).

*-- I may be missing something, but I don't see how JRuby needs different
> classes.*
>
> But there is in fact another serious limitation of the JVM that comes into
> play here, which might seem very obvious to [Charles Nutter] but not so much
> to Clojure folk: the smallest container unit of code for the JVM is a class.
> There is no such thing as a free-floating procedure that you can just invoke
> whenever. ...
>
> ...This is a problem not only for JRuby, but also for implementing
> delegates in the Java, a long-request feature. Java thus needs to do
> ridiculous things like this, which in C# (for example) would be done so much
> more elegantly:
>
> new Thread(new Runnable() { public void run() { ThisIsMyFakeDelegate();
> }).start();
>
> What we did above was create a new (anonymous) class as well as an
> instance! Clojure does essentially the same thing per fn, extending AFn
> instead of implementing Runnable.
>
> * Correction: In my original report, I said that Clojure creates only
> instances of AFn, not classes. I was misstating the situation: it's exactly
> one class and one instance per fn. Clojure extends AFn and simply overrides
> the correct method according to arity. ...
>

I'm still not seeing an problems that are different than Clojure. JRuby must
create a class for every method of every class in order to make the methods
hot-swappable at runtime. Clojure does the same thing for its IFns and for
the same reason. Both JRuby and Clojure would have to do this even if
invokedynamic didn't exist, because it is a problem more with classes and
class loading, than with invocation. I don't necessarily want to get
distracted by this...

*-- Clojure has similar needs. For instance, Clojure has protocol dispatch
> and multimethod dispatch as well as Var based dispatch. The multimethod
> dispatch does a look up in the derivation hierarchy. All of this stuff can
> change at runtime, just like in Ruby you can add methods to a class, change
> methods on a class, etc. I don't see how Clojure's dispatch needs are much
> different than what other dynamic languages are doing.
> *
> So, perhaps I'm not understanding how you are using the term "change at
> runtime" to describe both JRuby regular dispatch and Clojure's multimethod.
> ...
>

Correct me if I'm wrong, but multimethod dispatch calls a dispatch function
that returns a value. This value can then be used to inspect the global
derivation hierarchy. Then the result is used to find the right defmethod to
call, by basically looking up in a dictionary of methods. The global
derivation hierarchy can be changed at runtime which can cause different
dispatch values to be returned for the same arguments at different times.
Also, new defmethods can be added at runtime, which can change the
dictionary of methods. Protocol dispatch is similar, but doesn't go through
the global derivation hierarchy.

I believe there's already some form of caching implemented for multimethods
and protocols. That caching code could be replaced by bootstrap methods and
CallSites, which isn't really that exciting. However, I do believe that the
JVM can better optimize a MethodHandle in a CallSite than it can an IFn that
is fetched from a method dictionary at runtime. Perhaps that's just
speculation on my part. However, I've been hearing good things about
invokedynamic.

Plus, I believe with a CallSite the cache is more immediate than with a
dictionary lookup. With a dictionary lookup, you do the lookup every time
through the code path, but, as Charlie mentioned in another post, with a
MethodHandle you go straight from a reference to the implementation code
without having to do the lookup and without going through an interface. This
seems to be not only a performance boost, but provides more specific
information to the JVM, which would seem to improve optimizations.

Anyway, the biggest boost would seem to be calling Java methods from Clojure
without type hints.

Clojure's multimethod is "dynamic" in an entirely different way: the correct
> function is selected at runtime *according to the arguments* of the
> function. JVM-level linkage to the selected method would make no sense,
> because you'd be calling your bootstrapping method every single call!
>

Yeah, I've thought about that. That may be true. However, Clojure does use
caching for multimethod and protocol dispatch, and to whatever extent that
caching is successful it can be pushed down into the JVM. And again, to me
the advantage would be that the JVM has a MethodHandle directly to a method,
which would improve optimization potential, and also once they are
bootstrapped MethodHandles don't have check and recheck access levels and
types of arguments. MethodHandles are designed to remove the extra layers of
things you normally have to deal with when implementing dynamic languages on
the JVM.

You can argue that Clojure multimethods are inherently inefficient, and
> perhaps they are.
>
> One solution I could see is we allow to expand Clojure's deftypes into
> something more like classes/modules in other languages, in that deftypes
> could encapsulate functions as well as fields. But, this would turn Clojure
> into essentially object-oriented language, and I sincerely doubt Rich would
> allow for that to happen. :)
>
> Hope this helps clarify things! I don't think I've answered every single
> one of your points, but this discussion is already probably too long for
> more readers. Again, I encourage you to try to implement your ideas. The
> more eyes are on this problem, the better.
>
> -Tal

-- 
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