RFR: 8223504: improve performance of forall loops by better inlining of "iterator()" methods.
Sergey Kuksenko
sergey.kuksenko at oracle.com
Fri May 10 18:47:38 UTC 2019
Let me do a broader description.
When hotspot makes a decision to the "ultimate question compilation,
optimization and everything" inline or not inline there are two key
part of that decision. It is check of sizes (callee and caller) and
check of frequencies (invocation count). Frequency check is reasonable,
why should we inline rarely invoked method? But sometimes we loose
optimization opportunities with that.
Let's narrow the scenario. We have a loop and a method invocation before
the loop. Inline of the method is a vital for the loop performance. I
see at least two key optimizations here: constant propagation and scalar
replacement, maybe more. But if the loop has large enough amount of
iterations -> hotspot has large enough backedge counters -> but it means
that prolog is considered as relatively cold code (small amount of
invocation counter) -> that method (potentially vital for performance)
is not inlined (due to frequency/MinInlineThreashold cut off).
We can't say if inlining is important until we look into the loop (even
if there is a loop there). But we have to make a decision about inline
before that. So let's try to make reasonable heuristic and narrow the
scenario again. Limit our sight to Iterators. There is a very high
probability that after Iterable::iterator() invocation there is a loop
(covers all for-all loop). Also there is a high correlation between
collection size and amount of loop iterations. Let's inline all
iterators. I don't think the idea to analyze if "returned Iterator is a
freshly-allocated instance" makes sense. First of all it's unnecessary
complication. Moreover, I have results when we have chain of iterators,
hotspot can't inline the whole chain due to absence of profile (and/or
profile pollution), but partial inline of the chain have shown
performance benefits. To get more effective prediction if that
particular inline is important we should look not into the method, but
to the usage of the method results (into the loop).
About the first comment (to broad or to narrow check). I have to note
that this fix doesn't force inline for all methods with "iterator" name.
The fix only excludes frequency cut off. All other checks (by sizes) are
still in place. I did broader check for two reasons: to simplify
modifications and to have wider appliances when it works. I could narrow
it if you insist, but at the same time I think we have to make that
check broader - don't look into method name at all. If you have
something that returns Iterator - there will be loop after that with a
very high probability. So I'd vote for making that wider - check only
return type.
On 5/8/19 3:10 PM, Vladimir Ivanov wrote:
>> http://cr.openjdk.java.net/~skuksenko/hotspot/8223504/webrev.01/
> returned Iterator is a freshly-allocated instance
> src/hotspot/share/opto/bytecodeInfo.cpp:
>
> + if (callee_method->name() == ciSymbol::iterator_name()) {
> + if
> (callee_method->signature()->return_type()->is_subtype_of(C->env()->Iterator_klass()))
> {
> + return true;
> + }
> + }
>
> The check looks too broad for me: it returns true for any method with
> a name "iterator" which returns an instance of Iterator which is much
> broader that just overrides/overloads of Iterable::iterator().
>
> Can you elaborate, please, why did you decide to extend the check for
> non-Iterables?
>
> Commenting on the general approach, it looks like a good candidate for
> a fist-line filter before performing a more extensive analysis. I'd
> prefer to see BCEscapeAnalyzer extended to determine that returned
> Iterator is a freshly-allocated instance and decide whether to inline
> or not based on that instead. Among java.util classes you mentioned
> most iterators are trivial, so even naive analysis should get decent
> results.
>
> And then the analysis can be applied to any method which returns an
> Object to see whether EA may benefit from inlining.
>
> What do you think?
>
> Best regards,
> Vladimir Ivanov
>
>> On 5/7/19 11:56 AM, Aleksey Shipilev wrote:
>>> On 5/7/19 8:39 PM, Sergey Kuksenko wrote:
>>>> Hi All,
>>>>
>>>> I would like to ask for review the following change/update:
>>>>
>>>> https://bugs.openjdk.java.net/browse/JDK-8223504
>>>>
>>>> http://cr.openjdk.java.net/~skuksenko/hotspot/8223504/webrev.00/
>>> The idea sounds fine.
>>>
>>> Nits (the usual drill):
>>>
>>> *) Copyright years need to be updated, at least in bytecodeInfo.cpp
>>>
>>> *) Do we need to put Iterator_klass initialization this early in
>>> WK_KLASSES_DO? It feels safer to
>>> initialize it at the end, to avoid surprising bootstrap issues.
>>>
>>> *) Backslash indent is off here in vmSymbols.hpp:
>>>
>>> 129 template(java_util_Iterator,
>>> "java/util/Iterator") \
>>>
>>> *) Space after "if"? Also, I think you can use
>>> ciType::is_subtype_of instead here. Plus, since you
>>> declared iterator in WK klasses, SystemDictionary::Iterator_klass()
>>> should be available.
>>>
>>> 100 if(retType->is_klass() &&
>>> retType->as_klass()->is_subtype_of(C->env()->Iterator_klass())) {
>>>
More information about the hotspot-compiler-dev
mailing list