RFR: 8160302: Reduce number of lambdas created when loading java.util.regex.Pattern
claes.redestad at oracle.com
Wed Feb 1 21:12:39 UTC 2017
On 2017-02-01 20:48, Martin Buchholz wrote:
> I agree with the startup improvement goal.
> The need to do:
> + case "ALPHA": return ALPHABETIC();
> is pretty horrible (but we do worse in the name of performance). We'd
> like to be able to simply do:
> return Character::isAlphabetic;
> but probably we're stymied by hotspot's eagerness being per-method, not
I'm not sure I agree it's *that* horrible, but maybe I've grown
accustomed to somewhat horrible code... :-)
And no, while hotspot might the bytecode for a method eagerly, I'm
pretty sure the bootstrap method, which does the actual lambda
initialization and replace the instruction at the callsite, is not run
until executing the statement.
So, while I guess we could write "case "ALPHA": return
Character::isAlphabetic;" and get the same net result, I haven't
checked if that means we'd go through the hoop of spinning up that call
site at each location (ending up with the same thing) or if javac helps
ensure it'll be done at most once here.
As tests have been thoroughly run on this and time is running out,
I'd prefer contemplating cleaner/nicer ways of writing this particular
patch for 10 if you don't mind.
> Is the long-term solution to make hotspot's lambda initialization even lazier?
I guess it'd be interesting to try make lambdas like these (which
aren't used just after initialization) even lazier by emitting, say,
some thin MutableCallSite that defers real initialization to first use,
but not sure if feasible or if it'd even pay off except for cases like
these where you generate a lot of lambdas / method references but don't
use them right away. I'm sure others have thought more about this than
Somewhat orthogonally I do have plans to continue work on the static
pre-generation jlink plugin I introduced as part of 8086045, along with
other micro-optimizations to the involved java.lang.invoke code. This
helps make each call site lighter to spin up.
AOT might help, too, but stumbles once we actually have to generate a
new class dynamically, so it's not competing with the things we can
do with jlink currently...
All in all I'm sure we can inch closer and closer to negligible startup
overhead given time and dedication.
> On Wed, Feb 1, 2017 at 9:00 AM, Claes Redestad
> <claes.redestad at oracle.com <mailto:claes.redestad at oracle.com>> wrote:
> changes to java.util.regex in 9+119 has been cause for a number of
> regressions due to early use of lambdas, which has both helped motivate
> work to reduce the overall cost of lambda initialization, while
> in other
> cases the use of regexes could be reconsidered (VersionProps).
> While this work and workarounds has helped a lot, the changes to
> java.util.regex can still be the cause of noticeable regressions when
> using regular expressions that depend on predicates defined in
> java.util.regex.CharPredicate, simply because of how this class eagerly
> creates a substantial amount of lambdas during clinit.
> This patch makes the initialization lazy, which improves startup metrics
> without affecting performance of regular use.
> Bug: https://bugs.openjdk.java.net/browse/JDK-8160302
> Webrev: http://cr.openjdk.java.net/~redestad/8160302/webrev.01/
> PS. Yes, I know final is redundant on static methods, and realized I
> to remove them after turning constants into methods, but looking at
> it seems there's a convention of defining static methods final in
> this code
> already, so unless there is a lot of outrage I'd like to defer
> cleaning up this
> particular bikeshed.
>  https://bugs.openjdk.java.net/browse/JDK-8086045
>  12-15ms startup regressions due to generating and loading up to 60
> loaded classes, more early JIT compilations etc..
More information about the core-libs-dev