Daniel Sun created GROOVY-12264:
-----------------------------------

             Summary: Optimize the unrelated-default-method scan during class 
generation
                 Key: GROOVY-12264
                 URL: https://issues.apache.org/jira/browse/GROOVY-12264
             Project: Groovy
          Issue Type: Improvement
            Reporter: Daniel Sun


{{Verifier}} rejects a type that inherits two unrelated {{default}} methods of 
the same signature (GROOVY-10381, refined by GROOVY-11560). The scan runs in 
class generation for every type that lists two or more interfaces.

Class generation is a large share of compile wall time. The scan must stay 
cheap on the common path, where there is no conflict.

h3. Problem

* Stream / {{flatMap}} allocation on every such type.
* {{ClassNode.getAllDeclaredMethods()}} on the class and again on every 
interface. Each call rebuilds a full hierarchy method map and revisits 
inherited defaults.

On a wide or deep interface DAG the second point is quadratic in the number of 
interfaces.

h3. Approach

* Walk each interface's own methods ({{getMethods()}}) with loops. 
{{getAllInterfaces()}} already includes super-interfaces, so each {{default}} 
is visited once.
* Build the override-signature set only when two unrelated defaults actually 
collide, and only from the class plus its superclasses.
* Avoid the {{Optional}} allocation in {{MethodNode.isDefault()}}.

Before:

{code:java}
Set<String> declared = node.getAllDeclaredMethods().stream()
        .filter(m -> !m.isDefault())
        .map(MethodNodeUtils::methodDescriptorWithoutReturnType)
        .collect(Collectors.toSet());
node.getAllInterfaces().stream()
        .flatMap(iface -> iface.getAllDeclaredMethods().stream())
        .filter(MethodNode::isDefault)
        .forEach(method -> {
            // conflict check
        });
{code}

After:

{code:java}
for (ClassNode iface : node.getAllInterfaces()) {
    for (MethodNode method : iface.getMethods()) { // this interface only
        if (!method.isDefault()) {
            continue;
        }
        // conflict check; collect overrides only on a real collision
    }
}
{code}

Same conflict rules. No intended behaviour change.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to