Allocation of Lambdas that capture "this"

Brian Goetz brian.goetz at oracle.com
Wed Aug 20 22:43:34 UTC 2014


This is a classic tradeoff; you're loading down the Foo footprint (N 
more fields) and per-instance instantiation cost (eagerly instantiating 
N capturing lambdas per Foo instance at Foo-allocation time) by 
pre-computing all the this-capturing lambdas (or this-bound method 
references) you might need.  In your case, when your Foo objects are 
long-lived and these lambdas are re-used many times on the critical 
path, and you have real performance constraints, I could see it being a 
win.  (Of course I wouldn't recommend this approach for the other 
99.999% of cases.)




On 8/20/2014 6:00 PM, Richard Warburton wrote:
> Hi,
>
> I've recently being using Java 8 in a fairly performance critical project.
> We make extensive use of lambdas to implement callback handlers. For the
> most part this works well and the no-allocation on non-capturing lambdas
> makes for significantly nicer code than implementing the equivalent in Java
> 7.
>
> Unfortunately we still have quite a few callbacks where we capture no local
> variables, but want to refer to a field of the current class or even just
> call a method on the current class. Under the current implementation this
> still seems to require allocation. In our case we've hoisted up the code
> into the constructor and assigned it to a field, we then refer directly to
> the field at the callsite. Here's a pseudocode example just to clarify what
> I'm talking about.
>
> Allocating:
>
> public Foo() {}
>
> public int read() {
>      return queue.read(obj -> {
>          this.doSomethingWith(obj);
>          ...
>      });
> }
>
> Non-allocating:
>
> private final Consumer<Msg> readHandler;
>
> public Foo() {
>      readHandler = obj -> {
>          this.doSomethingWith(obj);
>          ...
>      };
> }
>
> public int read() {
>      return queue.read(readHandler);
> }
>
> Now this isn't the end of the world but it is choosing to write
> non-idiomatic code for purely performance reasons. Maybe I've missed
> something here and there are subtleties that I'm missing - I'm always happy
> to be corrected if I've misunderstood something.
>
> I'm sure people have thought about this one before and I'm bring up this
> specific issue not because "it looks like the JDK isn't doing something
> optimal" but because this was a problem in a concrete scenario. I spent a
> few hours this afternoon doing some memory profiling and this pattern was
> responsible for 6 or the top 8 allocation sites.
>
> regards,
>
>    Richard Warburton
>
>    http://insightfullogic.com
>    @RichardWarburto <http://twitter.com/richardwarburto>
>


More information about the lambda-dev mailing list