Allocation of Lambdas that capture "this"
Richard Warburton
richard.warburton at gmail.com
Wed Aug 20 22:00:49 UTC 2014
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