Skip to content

feat(java/gazelle): scaffold class-level dependency resolution#394

Merged
shs96c merged 6 commits into
bazel-contrib:mainfrom
shs96c:gazelle-class-names
Jan 19, 2026
Merged

feat(java/gazelle): scaffold class-level dependency resolution#394
shs96c merged 6 commits into
bazel-contrib:mainfrom
shs96c:gazelle-class-names

Conversation

@shs96c

@shs96c shs96c commented Nov 28, 2025

Copy link
Copy Markdown
Collaborator

Currently, the Java Gazelle plugin relies solely on package-level indexing for dependency resolution. This is inefficient for split packages in large corporate repositories, often requiring manual #gazelle:resolve directives.

This change introduces the architecture for class-level resolution:

Updates the resolution input pipeline to carry class-level import data alongside package data. Extends the Maven resolver to support querying by class name (with package fallback). Updates the resolution logic to prioritize precise class matches over broad package matches.

Currently, the Java Gazelle plugin relies solely on package-level indexing for dependency resolution. This is inefficient for split packages in large corporate repositories, often requiring manual #gazelle:resolve directives.

This change introduces the architecture for class-level resolution:

Updates the resolution input pipeline to carry class-level import data alongside package data.
Extends the Maven resolver to support querying by class name (with package fallback).
Updates the resolution logic to prioritize precise class matches over broad package matches.

This structure prepares the plugin for future improvements where class indices can be populated from jar files or external services, enabling automatic and precise resolution for split packages.
@shs96c shs96c force-pushed the gazelle-class-names branch 2 times, most recently from 4f6a8fd to 071a9de Compare November 28, 2025 17:49
@illicitonion

Copy link
Copy Markdown
Collaborator

Have you profiled this? I did a similar proof of concept a while ago and it increased both the time taken and memory consumption pretty significantly...

@shs96c

shs96c commented Jan 9, 2026

Copy link
Copy Markdown
Collaborator Author

Having used the gazelle plugin on a number of projects (particularly those that are migrating multi-project Gradle/Maven repos), split packages are a common problem. It may be worth taking the memory hit regardless.

I've not measured the change in resolution time. If it does increase significantly, perhaps we need to consider a different data structure for holding the data we need.

@shs96c

shs96c commented Jan 13, 2026

Copy link
Copy Markdown
Collaborator Author

Running a small benchmark on this repo, I get the following results (comparing this branch and main)

Time:
  Base (main):     1.134s
  Current (gazelle-class-names): 1.410s
  Difference:              24.3%

Memory:
  Base (main):     29MB
  Current (gazelle-class-names): 30MB
  Difference:              3.4%

This repo is pretty well-behaved, in that it doesn't have any split-packages so the memory consumption seems reasonable, but the timing difference seems surprising. I'll investigate.

This means that in the happy case (where there are no split packages)
the plugin is now as fast and as memory efficient as without them,
but memory (and time) will increase as the number of split packages
grows.
This change adds class-level resolution as a fallback when package
resolution is ambiguous:

1. During generation, cache each rule's exported classes and testonly status
2. On ambiguous package resolution, build a per-package class index lazily
3. Resolve individual class imports to their specific providing target
4. Maintain prod/test separation (test rules can see both, prod only sees prod)

Performance: The class index is built lazily per-package, only for packages
with multiple providers. Classes are NOT added to Gazelle's global RuleIndex,
avoiding O(classes) overhead for non-split-package resolution.

Maven collisions still produce the original helpful error messages with
`# gazelle:resolve` hints, as these cannot be resolved via class-level lookup.
@shs96c

shs96c commented Jan 13, 2026

Copy link
Copy Markdown
Collaborator Author

With the updates here. the difference between main and this branch are within touching distance:

Time:
  Base (main):     1.038s
  Current (gazelle-class-names): 1.082s
  Difference:              4.2%

Memory:
  Base (main):     29MB
  Current (gazelle-class-names): 30MB
  Difference:              3.4%

@jeffmace

jeffmace commented Jan 14, 2026

Copy link
Copy Markdown
Contributor

I did some profiling on our repository to understand what impact this would have. I've submitted the scripts used to do the profiling in #403. I need to review the units (KB/MB) used by the script but this should give you an idea.

Summary

  • Memory usage may be a little higher on average, but the maximum memory usage doesn't appear to be affected.
  • There isn't any noticeable change in CPU usage.
  • Running gazelle --mode=diff takes more than 3.5 minutes in our environment. This change appeared to cut ~15 seconds off of that.
  • CRITICAL: Testing with these changes tried to add //: to exports and deps across my repository. Update: This was caused by one of our local updates. I've resolved it and confirmed the PR does not have any negative effects.

Here are the details from running gazelle --mode=diff over 5 iterations with and without the changes.

Details

main
summary.txt
resource-usage.csv
rss-chart
cpu-memory-chart

gazelle-class-names
summary.txt
resource-usage.csv
rss-chart
cpu-memory-chart

@jeffmace

Copy link
Copy Markdown
Contributor

I updated the comment above to reflect that the behavior adding //: was caused by a local patch and not this PR.

@shs96c

shs96c commented Jan 14, 2026

Copy link
Copy Markdown
Collaborator Author

Is this with the most recent commits, or before I added them yesterday?

@jeffmace

Copy link
Copy Markdown
Contributor

Is this with the most recent commits, or before I added them yesterday?

It is based on e490fee which is your last commit from yesterday.

@shs96c

shs96c commented Jan 16, 2026

Copy link
Copy Markdown
Collaborator Author

@illicitonion, I think that addresses the size and speed concerns.

@shs96c shs96c merged commit e0fe781 into bazel-contrib:main Jan 19, 2026
7 of 8 checks passed
@shs96c shs96c deleted the gazelle-class-names branch January 19, 2026 10:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants