PlanetJava
Custom Search

java-vm-languages
[Top] [All Lists]

Re: Re: new milestone build for Renjin - R for the JVM

Subject: Re: Re: new milestone build for Renjin - R for the JVM
Date: Tue, 17 May 2011 07:39:43 -0700
Ah, I see you have to retain the original expression even after computing
the result.  My thunk designs assumed a language that doesn't let you
reflect that way and so could throw away the computation object once the
result was computed.
I think all the compiled JVM languages currently create a new jvm class for
each lambda expression (by which I also include the eta expansion typically
used to turn a "regular" function into an function value) and allocate an
object for each closure.  For a few function values it's not a big deal, but
over a large progam with lots of HOFs it's not cheap.  It costs time to load
the classes at startup and costs memory to hold the classes in memory (under
the current Snoracle JVM it uses precious permgen space).  There's also some
cost to allocate the function value objects, and cost to dispatch to them
(especially when hotspot determines the call is megamorphic).
Reflective calls to static methods would make the startup costs a bit
cheaper while making the runtime costs significantly heavier. Plus you'd
have to deal with the case when a function value needs to capture parts of
its environment - the environment would have to be bundled up in an object.
 If you're avoiding creating classes then you'd likely have to put the
environment in a dictionary (a hash table or similar), so that's even more
runtime cost.
I'd say go with the class approach until you decide that typical R programs
are overwhelming the JVM with classes and you think it's okay to take the
runtime hit of reflection + dictionaries.
On Tue, May 17, 2011 at 6:15 AM, Alexander Bertram 
<[email protected]>wrote:
>
>
>
> http://code.google.com/p/renjin/source/browse/trunk/core/src/main/java/r/lang/Promise.java
>
> My question for the JVM-niks out there is how feasable is it create a
> new jvm class for each thunk or function value?
> When you write a function in scala or clojure, does this get compiled
> into a new, separate class?
>
> I know invokedynamic will solve a lot of these problems, but in
> targeting java 6, is it worth economizing on the number of class,
> using for example reflection to dispatch a function call to a static
> method?
>
> Alex
>
>
> On May 17, 12:29 am, James Iry 
> <[email protected]> wrote:
> > /*
> >  * Along those lines I'm interested in the best way to implement
> > call-by-need
> >  * thunks on the JVM. A too-simplistic Java base class might look like
> >  */
> > abstract class Thunk1<T> {
> > private T memo = null;
> > private boolean evaluated = false;
> >
> > public final T compute() {
> > if (!evaluated) {
> > memo = compute();
> > evaluated = true;
> >
> > }
> > return memo;
> > }
> >
> > abstract T innerCompute();
> >
> > }
> >
> > /*
> >  * A thunk that lazily computes sqrt(1000) would look like
> >  *
> >  * new Thunk<Float> {
> >  *
> >  * @override public Float innerCompute() { return sqrt(1000); } }
> >  *
> >  * If you don't need nulls then you can get rid of the boolean and use
> memo
> >  * == null to indicate that it hasn't been computed.
> >  *
> >  * The problem with that simplistic approach is that the compute method
> will
> >  * hold on to a lot of structure that is no longer needed once the thunk
> has
> >  * been evaluated. A better approach looks more like
> >  */
> > public interface Thunk2<T> {
> > T compute();
> >
> > }
> >
> > public static <T> Thunk2<T> memoize2(final Thunk2<T> unmemoized) {
> > return new Thunk2<T>() {
> > private T memo = null;
> > private Thunk2<T> inner = unmemoized;
> >
> > @Override
> > public T compute() {
> > if (inner != null) {
> > memo = inner.compute();
> > inner = null;
> >
> > }
> > return memo;
> > }
> > };
> > }
> >
> > /*
> >  * To create a call-by-need thunk that computes sqrt(1000)
> >  *
> >  * memoize1(new Thunk<Float>() {
> >  *
> >  * @override public Float compute() { return sqrt(1000); } }
> >  *
> >  * That approach would need to be extended a bit if you want it to handle
> >  * exceptions - e.g. instead of just a memo field, add an exception field
> as
> >  * well and wrap the inner evaluation with a try/catch.
> >  *
> >  * An alternative memoizer uses a self-replacing thunk (that's what GHC
> >  * uses). It replaces the conditional with an extra level of indirection.
> >  * I've never benchmarked to know if self-replacing thunks work well on
> the
> >  * JVM. In Java it might look like
> >  */
> > public class MemoizedThunk<T> implements Thunk2<T> {
> > private T memo;
> >
> > public MemoizedThunk(T memo) {
> > this.memo = memo;
> >
> > }
> >
> > @Override
> > public T compute() {
> > return memo;
> >
> > }
> > }
> >
> > public static <T> Thunk2<T> memoize3(final Thunk2<T> unmemoized) {
> > return new Thunk2<T>() {
> > Thunk2<T> inner = new Thunk2<T>() {
> > @Override
> > public T compute() {
> > final T memo = unmemoized.compute();
> > inner = new MemoizedThunk<T>(memo);
> > return memo;
> >
> > }
> > };
> >
> > @Override
> > public T compute() {
> > return inner.compute();
> >
> > }
> > };
> > }
> >
> > /*
> >  * Again, exceptions might need to be added if they are part of your
> > language.
> >  *
> >  * One wrinkle with all of these options is that they don't play well
> with
> >  * Thunks that move between threads. For that you may need to add some
> >  * concurrency protection.
> >  *
> >  * Has anybody played with these or other alternatives here?
> >  */
> >
> > On Fri, May 13, 2011 at 8:46 AM, Alexander Bertram <
> [email protected]>wrote:
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > > Hi Rémi,
> >
> > > Thanks for taking a look!
> >
> > > I see now that you're right about the example with runif(). To be
> > > honest, I have more questions about compilation then running code at
> > > this point. I'm reading Modern Compiler Implementation by Appel and
> > > have started building the IRFactory, but R's lazy-non-pure-call-by-
> > > need-semantics-with-higher -order-functions are a bit dizzying for a
> > > compiler-novice like myself.
>
> --
> You received this message because you are subscribed to the Google Groups
> "JVM Languages" group.
> To post to this group, send email to 
> jvm-languages-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
> To unsubscribe from this group, send email to
> jvm-languages+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
> For more options, visit this group at
> http://groups.google.com/group/jvm-languages?hl=en.
>
>
-- 
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to 
jvm-languages-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en.
msgmiddle
<Prev in Thread] Current Thread [Next in Thread>
Current Sitemap | © 2012 planetjava | Contact | Privacy Policy