Skip to content

Performance Optimization: Formatting Modes & String Generation - #277

Merged
AndreasIgel merged 25 commits into
mainfrom
feature/performance-optimization-274
Sep 1, 2026
Merged

Performance Optimization: Formatting Modes & String Generation#277
AndreasIgel merged 25 commits into
mainfrom
feature/performance-optimization-274

Conversation

@AndreasIgel

@AndreasIgel AndreasIgel commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR introduces configurable formatting modes for generated builder source code and investigates/optimizes a major performance bottleneck in Roaster's string generation.

1. Configurable Formatting Modes (FormattingMode)

Adds a new compiler option -Asimplebuilder.formattingMode with three modes:

Mode Description Performance
JDT (default) Full Eclipse JDT formatter via Roaster.format() Slowest, highest quality
LIGHTWEIGHT Minimal cosmetic post-processing (tab→space, blank line collapsing, javadoc fixup) Fast, good-enough quality
NONE Raw output, no post-processing Fastest

This gives users control over the performance/quality trade-off, especially useful in large codebases where the JDT formatter is a bottleneck.

2. String Generation Investigation

During investigation, we identified that Roaster.toUnformattedString() internally calls CompilationUnit.rewrite(), an expensive Eclipse JDT operation that accounts for ~18s of processing time on the performance test project (1077 classes).

3. Performance Breakdown

Performance measured on the performance-test project (1077 builder classes):

Phase Before (main) After (this PR, JDT default) With LIGHTWEIGHT
String Generation ~18s (29%) ~18s (32%) ~18s (40%)
Formatting ~24s (39%) ~24s (42%) ~0s (0%)
Element Building ~14s (23%) ~14s (25%) ~14s (31%)
File Writing ~2s (3%) ~2s (3%) ~2s (4%)
Total ~62s ~62s ~45s

With LIGHTWEIGHT mode (-Dsimplebuilder.formattingMode=lightweight), formatting drops to ~0s and total processing time drops by ~27%.

Changes

Committed (this PR)

  • FormattingMode enum (core): New enum with JDT, LIGHTWEIGHT, NONE modes
  • SourceFormatter class (processor): Handles formatting dispatch based on mode, including lightweight formatter implementation
  • CompilerArgumentsEnum: Added FORMATTING_MODE argument
  • RoasterCodeGenerator: Uses SourceFormatter for formatting, removed inline formatting logic
  • BuilderProcessor: Reads formattingMode compiler argument and passes it through
  • FormattingModeTest: Comprehensive tests for both LIGHTWEIGHT and JDT modes
  • Documentation: Updated CONFIGURATION.md with formatting mode documentation

Future Optimization Opportunities

The investigation revealed that both major bottlenecks — String Generation (~18s) and JDT Formatting (~24s) — are fundamentally caused by Roaster's internal use of Eclipse JDT. The stashed reflection-based workaround only addresses the symptom, not the root cause.

The most promising path forward is to replace Roaster with a direct StringBuilder-based source generator. This would eliminate both bottlenecks at once:

  1. No rewrite() call — A StringBuilder approach generates the string directly, bypassing the expensive JDT CompilationUnit.rewrite() that accounts for ~18s.
  2. No JDT formatter needed — A well-structured StringBuilder generator can produce correctly indented and formatted code directly, eliminating the ~24s formatting phase.
  3. No reflection hacks — Removes the fragility of depending on Roaster's internal field names.
  4. Reduced dependencies — Eliminates the roaster-jdt dependency (and its shaded Eclipse JDT), reducing jar size and classpath complexity.

The existing SourceFormatter.lightweightFormat() already demonstrates that minimal post-processing (tab→space, blank line collapsing, javadoc prefixes) is sufficient for readable output. A StringBuilder generator would produce properly formatted code from the start, making even LIGHTWEIGHT post-processing optional.

Test Results

  • All 382 processor tests pass (committed changes)
  • Performance test project (1077 classes) builds successfully
  • FormattingModeTest verifies both LIGHTWEIGHT and JDT output quality

Closes #274

@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.59459% with 10 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...essor/classgen/roaster/RoasterSourceFormatter.java 96.17% 0 Missing and 6 partials ⚠️
...ers/simple/builders/core/enums/FormattingMode.java 71.42% 1 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@AndreasIgel
AndreasIgel merged commit fa6a2b6 into main Sep 1, 2026
8 checks passed
@AndreasIgel
AndreasIgel deleted the feature/performance-optimization-274 branch September 1, 2026 20:44
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.

Optimizing over all performance

1 participant