RFR 8228675: Resolve.findMethod doesn't cache interface type calculation

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Aug 7 21:04:19 UTC 2019

I've been catching up on this discussion - having written this code, I 
know this is tricky and also hard to optimize. Some efforts were already 
put in trying to minimize the lookups, but it seems now you are being 
affected by the cost of calling types.closure, which I understand.

Looking at the code again, I wonder if, before doing something, I'd like 
to step back and look at what the code is doing - specifically, I'm 
looking at this:

for (Type itype : itypes[iphase2.ordinal()]) {
                 if (!itype.isInterface()) continue; //skip j.l.Object 
(included by Types.closure())
                 if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
                         (itype.tsym.flags() & DEFAULT) == 0) continue;

So there are two cases where the type in the itypes array is actually 
not even looked at:

* the type is Object - ok, this is a corner case - because closure() 
will return also Object, fine

* if we're looking for defaults, and the type we have on our hands does 
not have the DEFAULT flag set, quit the search

Now it would be tempting to say that if a type doesn't have the DEFAULT 
flag set, then we can avoid adding its closure to the set - but that's 
wishful thinking; the flag is (currently) only set for interfaces that 
declare some default methods themselves. So, even if an interface 
doesn't declare any default method, we still have to search its 
superinterfaces, as some of those might.

And this is where the big lookup cost associated with default methods is 
coming from - we have to scan all superinterfaces in case _one_ might 
have some default in it that is more specific than the method we have 
already found.

I think one possible way to optimize this algorithm would be to actually 
do the opposite - e.g. to mark (as we scan them) interfaces whose 
hierarchies are NOT known to have any default methods in them. If we had 
such a detection mechanism, we could then prune entire families of 
interfaces (and their parents) from the findMethod lookup - which would 
bring back lookup performances with what we had before 8 (I'm assuming 
that was fast enough for the use cases brought up here?).

If you think that such an optimization is likely to give good results, 
then I'd rather invest on that: since here we'd simply require a flag to 
cache the interface hierarchy status w.r.t. default methods, I'm less 
worried that the caching mechanism will backfire and turn into cases of 
horrible memory footprint regression (we have seen that happening in the 
past with cases like these).



On 07/08/2019 11:25, Ron Shapiro wrote:
> Made the change for a WeakHashMap: 
> http://cr.openjdk.java.net/~ronsh/8228675/webrev.01/.
> Perhaps it would make better sense for this to be a field on 
> ClassType? That would avoid the need for managing a cache with weak keys.
> Do you have any guidance on how you approach tradeoffs in memory vs. 
> speed?
> On Mon, Aug 5, 2019 at 7:25 PM Vicente Romero 
> <vicente.romero at oracle.com <mailto:vicente.romero at oracle.com>> wrote:
>     not sure if we should add yet another cache to javac but in any
>     case it should be implemented with a: WeakHashMap,
>     Thanks,
>     Vicente
>     On 8/5/19 10:32 AM, Ron Shapiro wrote:
>>     Fair question.
>>     github.com/google/dagger <http://github.com/google/dagger>
>>     generates implementations of interfaces that implement a
>>     dependency injection graph. Sometimes, though not always, these
>>     interfaces have dozens if not hundreds of (super)interfaces which
>>     allow for builds to be sharded: each subsection of the build
>>     refers to the superinterface and then at the root of the build
>>     there is a union of them all. Naturally, this means this must be
>>     rebuilt on most/all changes to any subproject of the build.
>>     בתאריך יום ב׳, 5 באוג׳ 2019, 17:05, מאת Vicente Romero
>>     ‏<vicente.romero at oracle.com <mailto:vicente.romero at oracle.com>>:
>>         Hi Ron,
>>         Just out of curiosity, what is the context in which this
>>         issue arises? Naturally consuming more memory we can speed up
>>         javac but this can lead to other problems too.
>>         Thanks,
>>         Vicente
>>         On 8/5/19 8:24 AM, Ron Shapiro wrote:
>>>         Friendly ping
>>>         בתאריך שבת, 27 ביולי 2019, 0:05, מאת Ron Shapiro
>>>         ‏<ronshapiro at google.com <mailto:ronshapiro at google.com>>:
>>>             Hi,
>>>             Please review this change to speed up Resolve.findMethod
>>>             for large classes that have large numbers of
>>>             (super)interfaces
>>>             webrev: http://cr.openjdk.java.net/~ronsh/8228675/webrev.00/
>>>             bug: https://bugs.openjdk.java.net/browse/JDK-8228675
>>>             Thanks,
>>>             Ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20190807/e5925b18/attachment-0001.html>

More information about the compiler-dev mailing list