Skip to content

IClasspathEntry.isTest() iterates extra attributes array on every call and can become a perfromance hot-spot #4927

@laeubi

Description

@laeubi

During analysis of two heapdums shared here the following issue was discovered as a hotspot that can benefit from optimization:

Performance Data

Metric WITH transitive WITHOUT transitive Ratio
Self time (µs) 2,233,733 366,222 6.1×

Description

IClasspathEntry.isTest() is a default interface method that iterates over the entire getExtraAttributes() array on every invocation:

default public boolean isTest() {
    for (IClasspathAttribute attribute : getExtraAttributes()) {
        if (IClasspathAttribute.TEST.equals(attribute.getName()) && "true".equals(attribute.getValue()))
            return true;
    }
    return false;
}

This method is called on every classpath entry during classpath expansion and package fragment root computation. With transitive dependencies, the number of classpath entries grows, and isTest() is called on each one — often multiple times during the same build phase. The same pattern exists for isWithoutTestCode().

Suggested Fix

Override isTest() in ClasspathEntry (the concrete implementation) to cache the result. The extra attributes are immutable after construction, so the result can be computed once and stored:

// In ClasspathEntry.java
private int cachedIsTest = -1; // -1 = not computed, 0 = false, 1 = true

@Override
public boolean isTest() {
    if (cachedIsTest == -1) {
        cachedIsTest = IClasspathEntry.super.isTest() ? 1 : 0;
    }
    return cachedIsTest == 1;
}

Alternatively, compute isTest and isWithoutTestCode in the ClasspathEntry constructor and store as boolean fields, since these are queried on almost every entry.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions