RFR: 8223504: improve performance of forall loops by better inlining of "iterator()" methods.

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Mon May 27 11:16:36 UTC 2019

> http://cr.openjdk.java.net/~skuksenko/hotspot/8223504/webrev.03/


Best regards,
Vladimir Ivanov

> Now, only return type is checked. It works the same way on all forall 
> loops. Besides it perfectly works on "descendingIterator()" methods and 
> all other methods returning iterator but having other names like 
> Enumeration::asIterator.
> On 5/22/19 10:47 AM, Vladimir Ivanov wrote:
>> Thanks for the thorough explanation, Sergey.
>> What I like about the patch you propose is its simplicity.
>> More accurate heuristic which takes inlining effects into account 
>> (e.g., on EA) would scale to a much wider range of use cases and C2 
>> has a rich toolkit to make such heuristic possible, but it would 
>> definitely require more effort.
>> Thinking about it for a while, I agree with your proposal: the 
>> heuristic is acceptable for the case of iterators, the benefits are 
>> evident, and risks (with overinlining and premature inlining) are low.
>> I still hope there'll be a more generic solution available at some 
>> point which will supersede such special case for Iterable.
>> Regarding the check itself, I'm in favor of limiting it 
>> toIterable::iterator() overrides/overloads, but I'm OK with a more 
>> generic check on return type.
>> Best regards,
>> Vladimir Ivanov
>> On 10/05/2019 21:47, Sergey Kuksenko wrote:
>>> 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