Stats: Effect of translating lambda with condy, and folding, on JDK
Brian Goetz
brian.goetz at oracle.com
Wed Mar 21 16:07:23 UTC 2018
Vicente has run some statistics on the effect of two optimizations,
using the JDK as a corpus:
- translating non-capturing lambdas and method refs using condy
instead of indy
- constant folding
Translating lambdas using condy instead of indy should result in two
improvements:
- condy is lighter weight at link time (faster startup)
- better sharing of duplicated method references / lambdas
Currently, if a class has two identical method references, they will
each get their own indy site, which will share a
Constant_InvokeDynamic_info (and bootstrap methods entry.) But, since
each indy is linked independently, linkage will be done redundantly,
resulting in duplicate proxy classes being spun. If we convert this
over to condy, we'll have two LDCs of the same constant, which only gets
resolved once.
As a baseline, we collected counts of { lambda, method ref } x {
capturing, not } x { serializable, not }, in the corpus (the JDK):
Ser NonSer
Lambda Stateless 7 953
Stateful 10 1688
Ref Stateless 23 712
Stateful 528
And we collected counts of indy constant pool entries and indy
instructions that correspond to LambdaMetafactory:
#indyCP: 3683
#indyInsn: 3966
We would expect to see a count of indy instructions equal to the number
of nonserializable lambdas/mrefs plus twice the number of serializable
lambdas/mrefs (since there is a twin capture site in the $deserialize$
method.) We got close; we expected 3961, but saw 3966. The remaining
five are accounted by lambdas that were in contexts that got duplicated
by the compiler (finally blocks, instance initializers.)
The difference between the indy instructions and CP entries has to do
with duplicated lambdas or methods refs. We'd expect to see these for
serializable, for those that are implicitly duplicated as above, and
also when method refs are explicitly duplicated within a classfile. So
we saw ~230 reuses that must be the result of explicit source
duplication of method refs.
We then ran the same stats with translating non-capturing lambdas and
non-capturing (static, unbound, and constructor) method references using
condy.
#indyCP 2156 // shared=125
#indyInsn 2281
#condyCP 1527 // shared=158
#condyLDC 1685
What this means is that approximately 40% of lambdas and method refs
could be diverted from indy to condy. Any explicitly duplicated method
refs would get the benefit of constant pool sharing.
When the lambda deduplication effort completes, the numbers should get
better, as there will be more candidates for sharing of CP entries
(currently, even identical lambdas get their own lambda$nn method.)
Looking ahead, the richer constant propagation will help as well, as it
may push some lambdas from the "capturing" to the "non-capturing"
column. Not only are non-capturing lambdas more performant today, but
then they also become candidates for condy translation.
The JDK is probably not an ideal corpus to run this on; if someone wants
to try the stats gathering patch on a different corpus, that would be great.
More information about the amber-dev
mailing list