bazel: add a GraalVM native-image server - #30282
Open
sluongng wants to merge 5 commits into
Open
Conversation
Contributor
Author
|
@fmeum Would you be willing to take a look at this GraalVM native-image prototype? The PR is structured as an eight-commit walkthrough and includes the benchmark scope and tradeoffs in the description. |
fmeum
self-requested a review
July 15, 2026 10:48
fmeum
reviewed
Jul 15, 2026
| // * is internal to CompressedTarFunction. | ||
| // This is best served by a cryptographically random UUID, generated at startup. | ||
| private static final String NAME = UUID.randomUUID().toString(); | ||
| // Native Image needs a stable name to register this charset ahead of time. The marker remains |
Collaborator
There was a problem hiding this comment.
The second part of the comment is written like a PR description, but it's a code comment. Replace "remains" with "is"
Collaborator
|
@sluongng The first three commits LGTM with one comment, could you send them as separate PRs? |
Contributor
Author
|
yeah let me cherry-pick them to separate PRs |
sluongng
force-pushed
the
sluongng/graalvm-native-upstream
branch
from
July 15, 2026 11:29
cbbf732 to
2eb8024
Compare
This was referenced Jul 15, 2026
copybara-service Bot
pushed a commit
that referenced
this pull request
Jul 16, 2026
This change is needed because some Java runtimes omit the java.home system property. Passing that null value into Bazel path encoding makes bazel info fail instead of reporting the available runtime metadata. Return unknown when the property is absent, matching the existing fallback for an unencodable value. Cover the exact output while leaving normal JVM path normalization unchanged. Extracted from #30282. Closes #30286. PiperOrigin-RevId: 949017883 Change-Id: I8491dd68298640d72cc0eb621410da0d367da89f
copybara-service Bot
pushed a commit
that referenced
this pull request
Jul 17, 2026
This change is needed because some Java runtimes expose no garbage collector MXBeans. Bazel treats an empty list as an unsupported collector and aborts server startup before it can run a command. Treat an empty bean list as an environment without memory-pressure notifications. Log a warning when the listener is created because optional caches cannot be limited based on heap usage and peak memory may be higher. Preserve the existing error for a non-empty list of unknown collectors, so ordinary HotSpot diagnostics remain unchanged. Cover listener initialization, reset, and warning output with no collector beans. Extracted from #30282. Closes #30285. PiperOrigin-RevId: 949540973 Change-Id: I9f6cbf775544d4efe44014b94e0c5b74c8858f3f
copybara-service Bot
pushed a commit
that referenced
this pull request
Jul 21, 2026
Commons Compress decodes UStar names with a caller-selected charset but always decodes PAX paths as UTF-8. Bazel uses a private marker charset to distinguish those sources and preserve raw UStar bytes without corrupting PAX Unicode names. Native Image cannot resolve that charset when its lookup name changes at startup and its provider is hidden from enumeration. Give the charset a stable private name, keep the collision marker random, and expose the provider charset for ahead-of-time registration. Add a Latin-1-only PAX regression because names outside Latin-1 masked the lookup ambiguity in the existing test. Extracted from #30282. Closes #30284. PiperOrigin-RevId: 951408843 Change-Id: I96e3e0e322ec6d833987b77631b8f588048c4009
sluongng
force-pushed
the
sluongng/graalvm-native-upstream
branch
from
July 22, 2026 08:07
2eb8024 to
58c1528
Compare
Bazel cannot use the general rules_graalvm native_image rule because its server needs generated reachability metadata and the libmanagement_ext.so side output. The earlier genrule prototype also hid inputs and resource requirements from remote execution. Add a Bazel-specific Starlark rule that models metadata generation, bundle creation, and image compilation as declared actions. Pin Oracle GraalVM 25.1.3 for Linux x86-64 and preserve the G1 side outputs needed by the packaged server. Keep Bazel internal paths in Latin-1 strings while retaining UTF-8 native encoding. Register the private tar charset and defer platform, Netty, and encoding state whose image-build initialization is unsafe. Enable native thread-dump monitoring so SIGQUIT preserves the existing debugging contract. This commit defines the build mechanism and auditable metadata. Packaging and remote-provider placement remain separate concerns.
The existing Bazel package always installs A-server.jar and starts it through a JVM. A compiled server therefore needs a matching archive and client launch path before it can serve normal Bazel commands. Add a native package that installs A-server-native and its required JNI library without carrying the redundant server jar or build diagnostics. Teach a dedicated client build to start that executable without JVM-only arguments, while leaving the existing JVM package and client unchanged. Pass the common startup protocol and logging properties to the native server. Select Latin-1 for Linux JNU path conversion while retaining a UTF-8 process locale. Reload LogManager configuration at native startup because Native Image initializes it while building the image. Limit the artifact to Linux x86-64. Provider-specific placement and resource hints remain outside this portable package.
This change is needed because Chicory compilation defines Java classes at runtime, which the closed-world GraalVM image does not support with the selected G1 runtime. Enabling the repository Wasm compilation flag aborts an otherwise portable native Bazel operation. Treat compile as an optimization hint under Native Image and use the Chicory interpreter there. Keep compiled execution unchanged on the JVM, and update the flag and API documentation to state the native behavior. Exercise the interpreter while the compilation feature flag is enabled so the native compatibility path cannot silently regress.
This change is needed because the shell harness always selects the packaged JVM Bazel, so it cannot measure native-image compatibility through existing integration tests. Add a build setting and runfiles wrapper that select the native binary. Keep its large output and install state outside constrained test sandboxes, capture server diagnostics, and avoid cleanup commands when a test never started an inner Bazel server. Retain the existing JVM assertions and add native contracts instead of skips. Prove that server_javabase remains accepted without executing a JVM, stall logging initialization to exercise the client startup timeout, and require SIGQUIT to emit a native thread dump without restarting the server. Every selected native test function now executes assertions.
This change is needed because native-image performance claims are not actionable without a repeatable comparison against the JVM baseline and the non-PGO native binary. Add instrumented and profile-guided image targets plus a Hyperfine report runner. Train over an incremental commit sequence, prewarm disk and repository caches in an unmeasured pass, restart daemons between runs, and retain Bazel command and memory profiles for later attribution. Require a dedicated detached worktree before any reset or clean operation. Keep generated PGO data outside the source tree except for the checked, temporary copy consumed by the PGO build. Leave remote build configuration as an explicit caller choice.
sluongng
force-pushed
the
sluongng/graalvm-native-upstream
branch
from
July 22, 2026 08:37
58c1528 to
2a4af3a
Compare
sluongng
marked this pull request as ready for review
July 22, 2026 08:38
Contributor
Author
|
@fmeum, the first 3 commits are now in master, so I rebased this PR to get rid of them. The setup now has 5 instead of 8 commits. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR adds an opt-in Linux x86-64 Bazel server compiled ahead of time
with Oracle GraalVM Native Image 25.1.3. The regular JVM-based Bazel
distribution remains the default and its behavior is unchanged.
The result is a native Bazel server that starts, loads, and analyzes a
representative incremental workload faster while using materially less
resident memory:
The benchmark covers 30 sequential revisions with three complete
repetitions per variant, warm disk and repository caches, and equal
8 GiB committed heaps. It runs
build --nobuild //src:bazel-bin-dev,so these numbers specifically measure process/server startup, loading,
and analysis rather than execution-heavy build throughput.
Prerequisites merged separately
Three compatibility fixes previously carried at the bottom of this
stack have landed separately and are now provided by the rebased
master:private tar marker charset.
runtimes without garbage-collector MXBeans.
missing
java.homeproperty.Those changes remain prerequisites for the native server, but no longer
appear in this PR's diff.
Commit stack
build: add a Bazel native-image ruleAdds the native-image rule, GraalVM 25.1.3 toolchain pin,
reachability metadata generation, JNI/reflection configuration, and
the
libmanagement_ext.soside output needed by the G1 image.bazel: launch a native-image serverPackages the native server into a Bazel binary and adds a dedicated
client path that preserves Bazel's client/server and logging
protocols without passing JVM-only startup arguments.
repository: interpret Wasm in native imagesKeeps Chicory's compiled path on the JVM and falls back to its
interpreter under Native Image, where dynamic class definition is
unavailable.
test/shell: exercise native BazelRoutes a focused shell/integration suite through the native binary,
covering startup options, client behavior, sandboxing, remote
execution, Unicode, Wasm, run/test behavior, and reduced-JDK
packaging.
benchmark: compare native Bazel with PGOAdds reproducible JVM, native, instrumented, and PGO benchmark
targets and preserves the generated timing, profile, and memory
artifacts.
The support is intentionally scoped and opt-in:
approximately 168 MiB for JVM Bazel; the measured PGO package is
approximately 292 MiB.
3m32s and peaked at 11.5 GiB RSS. The image and PGO targets are
therefore tagged
manualand are only built when explicitlyrequested or by the native integration configuration.
checked into the repository.
reachability-option warnings. These are visible maintenance points,
not hidden assumptions.
Motivation
Bazel commands in incremental development loops can spend a meaningful
fraction of their time starting the server, loading packages, and
performing analysis. This prototype demonstrates that an AOT-compiled
server can reduce both latency and resident memory while retaining
Bazel's existing client/server architecture and exercising
representative integration behavior.
This is not a proposal to replace JVM Bazel. It establishes an opt-in,
tested, and reproducible foundation for evaluating native Bazel,
measuring its tradeoffs, and deciding which pieces should be generalized
or moved into shared GraalVM rules over time.
Build API Changes
No.
This adds internal build and test targets plus a test-only build
setting. It does not change a public Starlark API, provider, native
rule, default command-line behavior, or the JVM distribution.
Under the native-image server only, the existing Wasm compilation mode
becomes best-effort and falls back to interpretation because Native
Image cannot define new classes dynamically.