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 10:48:03 -0400
Absolutely stick with the compiled version. Newer versions of the JVM
will provide automatic improvements for class memory management, so
your language will be hitting that wonderful JVM sweet spot of
becoming faster by sitting there.
Take a serious look at MethodHandles and the java.lang.invoke package
that come in Java 7. They're basically a closure implementation at the
bytecode level.
~~ Robert.
On Tue, May 17, 2011 at 10:39 AM, James Iry 
<[email protected]> wrote:
> 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
> 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