Skip to content

Optimize the Temurin tool-cache fast path #1177

Description

@brunoborges

Description:
Optimize setup-java@v6 for its most common hosted-runner scenarios: Temurin is requested, the matching JDK is already installed in the runner tool cache, and dependency caching is either disabled or enabled.

The current setup bundle eagerly imports every distribution implementation and cache-related dependencies before it knows which path the job needs. In addition, dependency cache restoration starts only after Java installation and subsequent local configuration have completed.

Address these three related opportunities together:

  1. Lazy-load the selected distribution

    Avoid eagerly loading every distribution installer through distribution-factory.ts. Load only the implementation selected by the distribution input. The common distribution: temurin path should not initialize code, metadata, or dependencies used only by Zulu, Microsoft, Oracle, GraalVM, OpenJDK, and other distributions.

  2. Load cache dependencies only when caching is enabled

    When the cache input is absent, the setup path should not initialize @actions/cache, @actions/glob, or their transitive Azure Storage dependencies. This may require moving cache feature detection out of the shared util.ts module and dynamically importing the cache module only after a non-empty cache input is validated.

  3. Overlap dependency cache restoration with local Java setup

    When caching is enabled, start dependency cache key computation and restoration as early as safely possible, then allow it to run concurrently with the Temurin tool-cache lookup and local configuration. Await the restore before the action exits so dependencies are fully available to the next workflow step.

    Conceptually:

    const cacheRestore = cacheInput ? startCacheRestore() : undefined;
    
    await installAndConfigureJava();
    await configureAuthenticationAndToolchains();
    
    await cacheRestore;

    The final design must preserve deterministic failures. If Java setup fails, do not let an in-flight cache rejection become unhandled. If cache restoration fails, preserve the action's existing failure behavior. Inputs and prerequisite validation should happen before launching concurrent work where necessary.

Acceptance criteria:

  • A Temurin tool-cache hit does not load other distribution implementations.
  • A run without the cache input does not load the cache client, glob implementation, or Azure Storage dependencies.
  • A cache-enabled run begins cache work before the local Java/configuration path has completed and awaits it before returning.
  • Java and cache errors remain surfaced consistently, with no unhandled promise rejections or silent failures.
  • Existing outputs, environment variables, Maven settings/toolchains, problem matcher behavior, and cache state remain unchanged.
  • Multi-version Java setup and java-version-file behavior remain correct.
  • Unit tests prove conditional module loading and true concurrency rather than only checking final call order.
  • Distribution-factory tests continue covering every supported distribution.
  • The committed dist/setup/index.js is rebuilt and its size is compared before and after.

Performance validation:

Benchmark the released baseline and proposed implementation on GitHub-hosted Linux, Windows, and macOS runners using Temurin 17, 21, and 25 where preinstalled. Capture at least these scenarios:

  • Tool-cache hit, dependency caching disabled.
  • Tool-cache hit, Maven cache hit and miss.
  • Tool-cache hit, Gradle cache hit and miss.

Use multiple repetitions and report median and p95 setup-step duration. The change should demonstrate a measurable improvement in the no-cache path and must not regress cache-hit or cache-miss duration. The cache-overlap portion should only be retained if it improves wall time beyond normal runner variance.

Justification:
Temurin on GitHub-hosted runners is one of the action's highest-volume paths. When the requested JDK is already in the tool cache, setup-java performs no download, so bundle initialization and local orchestration become a meaningful share of the step duration. Eagerly initializing unused distributions and cache infrastructure adds overhead to every such job.

Reducing startup work improves both cached and uncached builds. Starting cache restoration earlier can additionally hide part of its latency behind work the action must already perform. Because setup-java runs across large CI fleets, even small repeatable reductions in the dominant path translate into lower billed runner time and faster feedback for customers.

Are you willing to submit a PR?
Yes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestNew feature or request to improve the current logicmaintenanceInternal refactors/chore work

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions