Reified Lambda Functions

Howard Lovatt howard.lovatt at iee.org
Fri Jan 8 06:02:04 PST 2010


On my machine using the server JVM the following:

  static double reduce(final double[] ds, double initial, final
_Callable_double_double_double reducer) {
    for (final double d : ds) { initial = reducer.callPrimitive(initial, d);
}
    return initial;
  }

  static <T> T reduce(final T[] ts, T initial, final _Callable_2<? extends
T, ? super T, ? super T> reducer) {
    for (final T t : ts) { initial = reducer.call(initial, t); }
    return initial;
  }

  static <T> void time(final _Callable_0<T> c) {
    final long start = System.currentTimeMillis();
    final T result = c.call();
    final long finish = System.currentTimeMillis();
    System.out.println(c + " took " + (finish - start) + " ms and returned "
+ result);
  }

  static void timeTest() {
    final int size = 1024 * 1024;
    final double[] ds = new double[size];
    final Double[] ts = new Double[size];
    for (int i = 0; i < size; i++) { ts[i] = ds[i] = i; }
    final _Callable_double_double_double sumDs = new
_Callable_double_double_double() {
      @Override public double callPrimitive(final double a1, final double
a2) { return a1 + a2; }
    };
    time(new _Callable_double() {
      @Override public double callPrimitive() { return reduce(ds, 0, sumDs);
}
      @Override public String toString() { return "double[] test"; }
    });
    final _Callable_Dble_Dble_Dble sumTs = new _Callable_Dble_Dble_Dble() {
// Compiler bug! Should be Double not Dble
      @Override public Double call(final Double a1, final Double a2) {
return a1 + a2; }
    };
    time(new _Callable_Dble() { // Compiler bug! Should be Double not Dble
      @Override public Double call() { return reduce(ts, 0.0, sumTs); } //
note 0.0 - annoying inference bug!
      @Override public String toString() { return "Double[] test"; }
    });
  }

Gives:

double[] test took 12 ms and returned 5.497552896E11
Double[] test took 470 ms and returned 5.497552896E11

That is some considerable penalty to pay for erasure. From comments made by
Doug Lea (
http://mail.openjdk.java.net/pipermail/closures-dev/2009-November/000342.html)
 I believe the penalty in multi-core applications is even larger.

That is why I say you need to reify lambdas to make ParallelArray
worthwhile.

 -- Howard.

2010/1/7 Mark Thornton <mthornton at optrak.co.uk>

> Fredrik Öhrström wrote:
>
>> Hi Howard!
>> I am curious, what are the primary reasons for reifying lambdas? You
>> mention performance... but for example if a lambda(closure) is used  as the
>> body of a loop, the  optimizing JVM will inline the iteration code from the
>> collection class and this will in turn inline the lambda as well. Thus
>> effectively types outside of the lambda will be propagated into the lambda
>> when the code is optimized since they will be part of the same AST.
>>
>>
> I wish I could be more confident that such transformations would in fact
> take place where appropriate. Especially as the tiered compiler appears to
> have died or gone into hibernation.
>
> Mark Thornton
>
>
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email______________________________________________________________________
>



-- 
 -- Howard.


More information about the lambda-dev mailing list