google / google/ksp

[KSP2][Bazel] ~50% incremental build regression vs KSP1

Open
#2,960 4 comments 1 reaction 0 assignees View on GitHub
enhancement P3 performance
Dominant language
Kotlin
Stars
3.5k
Forks
415
Avg merge
1d 2h
Merged PRs (30d)
53

Description

### Environment
- KSP 2.3.9 · Kotlin 2.3.21 · Bazel 9.1 · rules_kotlin persistent multiplex workers
- Same codebase, same modules, same processors — only KSP version changed

## Numbers (5 runs, warm worker, incremental ABI-change build, 111-file module)

| | KSP1 `KotlinKsp` | KSP2 `KotlinKsp2` | Δ |
|---|---|---|---|
| KSP action total | 1699ms | 2515ms | +48% |
| `SymbolProcessor.process()` r1 | 1083ms | 1722ms | +59% |
| `createAASession()` cold | *(none)* | 3083ms | — |

## Root cause

KotlinSymbolProcessing.createAASession() bootstraps a full StandaloneAnalysisAPISession + MockProject + FIR providers on every Bazel action invocation — once per module per build. KSP1 paid zero session cost: it ran as an AnalysisHandlerExtension inside the kotlinc invocation and received the pre-built BindingContext from the compiler for free.

On a cold worker, createAASession() alone takes 3083ms — driving the full KSP action to 7439ms on first request. Even warm (317ms session + 383ms post-gap = 700ms before the first processor call), KSP2 overhead exceeds KSP1's entire action.

## What I tried

**PsiResolutionStrategy**: session setup improved by ~50%, but overall KSP action time was still not viable for our annotation-heavy processors that need full type resolution.

## My theory

createAASession() is faster on warm requests (317ms vs 3083ms cold), confirming some IntelliJ singleton state survives in the JVM between requests. Yet MockProject and KaSourceModule are still reconstructed every time. Caching the session across requests for the same processor classpath could close most of the gap.

## Question

Is the ~50% warm regression and 4× cold penalty expected when migrating from KSP1 to KSP2 in Bazel persistent multiplex workers, or is there a specific configuration or usage pattern we should adopt to avoid paying the full createAASession() cost per action?
Might be related to: [Issue](https://github.com/google/ksp/issues/2959)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.