Skip to content

Performance Tracker for Annotation Processing - #258

Open
AndreasIgel wants to merge 5 commits into
mainfrom
feature/performance-test-project
Open

Performance Tracker for Annotation Processing#258
AndreasIgel wants to merge 5 commits into
mainfrom
feature/performance-test-project

Conversation

@AndreasIgel

Copy link
Copy Markdown
Collaborator

Performance Tracker for Annotation Processing

Implements a hierarchical performance tracking system for the simple-builders annotation processor, enabling detailed phase-by-phase timing analysis via -Asimplebuilder.performanceTracking=true. Prepares for the analysis in #93.

Summary

  • PerformanceTracker interface with No-Op pattern for zero overhead when disabled
  • ActivePerformanceTracker with hierarchical phase reporting using tree connectors (├─, └─, │)
  • Phase constants publicly shared on PerformanceTracker interface
  • Per-generator and per-enhancer timing with call counts
  • Top-20 slowest classes with field/collection counts
  • performance-test Maven module scaffold (not part of default build)

Changes

New files

  • processor/.../processing/logging/PerformanceTracker.java — Interface with 14 public PHASE_* constants
  • processor/.../processing/logging/ActivePerformanceTracker.java — Full implementation with hierarchical report
  • processor/.../processing/logging/NoOpPerformanceTracker.java — Zero-overhead no-op implementation
  • performance-test/pom.xml — Maven module for future performance test classes

Modified files

  • processor/.../BuilderProcessor.java — Phase tracking for Configuration Resolution, Builder Definition Extraction, DTO Mapping, Code Generation
  • processor/.../classgen/roaster/RoasterCodeGenerator.java — Sub-phase tracking inside individual methods (Source Construction, Element Building, Class Creation, Class Metadata, Fields, Constructors, Methods, Nested Types, Class Annotations, String Generation, Formatting, File Writing)
  • processor/.../generators/registry/GeneratorRegistry.java — Per-generator and per-enhancer timing wrappers
  • processor/.../processing/ProcessingContext.javaPerformanceTracker integration based on compiler argument
  • processor/.../processing/CompilerArgumentsEnum.java — New PERFORMANCE_TRACKING enum value
  • processor/.../processing/BuilderConfigurationReader.java — Updated import for moved ProcessingLogger
  • processor/.../processing/logging/ProcessingLogger.java — Moved from processing to processing.logging package
  • processor/.../generators/integration/JacksonModuleGenerator.java — Updated import for moved ProcessingLogger
  • processor/src/test/.../RoasterCodeGeneratorResilienceTest.java — Updated constructor call for NoOpPerformanceTracker
  • pom.xmlperformance-test module added to performance-test profile

Phase Hierarchy

├─ Configuration Resolution
├─ Builder Definition Extraction
├─ DTO Mapping
└─ Code Generation
   ├─ Source Construction
   │  ├─ Element Building
   │  │  ├─ Class Creation
   │  │  ├─ Class Metadata
   │  │  ├─ Fields
   │  │  ├─ Constructors
   │  │  ├─ Methods
   │  │  ├─ Nested Types
   │  │  └─ Class Annotations
   │  ├─ String Generation
   │  └─ Formatting
   └─ File Writing

Percentages are calculated relative to the parent phase. All phase names are defined as public String constants on PerformanceTracker and referenced via static imports at call sites.

Sample Report

simple-builders: PERFORMANCE REPORT
================================
Total classes processed: 8
Total processing time: 1.7s

Phase breakdown:
├─ Configuration Resolution: 0.0s (0.7%)
├─ Builder Definition Extraction: 0.1s (3.7%)
├─ DTO Mapping: 0.0s (0.2%)
└─ Code Generation: 1.5s (88.5%)
   ├─ Source Construction: 1.4s (98.0%)
   │  ├─ Element Building: 0.6s (43.9%)
   │  │  ├─ Class Creation: 0.4s (58.7%)
   │  │  ├─ Class Metadata: 0.0s (1.1%)
   │  │  ├─ Fields: 0.1s (16.6%)
   │  │  ├─ Constructors: 0.0s (2.2%)
   │  │  ├─ Methods: 0.1s (17.0%)
   │  │  ├─ Nested Types: 0.0s (3.1%)
   │  │  └─ Class Annotations: 0.0s (1.4%)
   │  ├─ String Generation: 0.6s (39.3%)
   │  └─ Formatting: 0.2s (16.7%)
   └─ File Writing: 0.0s (2.0%)

Average per class: 207.6ms

Top 8 slowest classes:
  1. BookDto - 1053.2ms (19 fields, 3 collections)
  2. PersonDto - 102.4ms (5 fields, 1 collections)
  ...

Top 5 slowest MethodGenerators:
  1. BasicSetterGenerator - 0.0s (39 calls, 0.15ms/call)
  ...

Top 5 slowest BuilderEnhancers:
  1. CoreMethodsEnhancer - 0.0s (8 calls, 0.32ms/call)
  ...

Design Decisions

  • No-Op pattern: When tracking is disabled, NoOpPerformanceTracker is used — all methods are empty, allowing JIT to eliminate calls entirely. No boolean check per invocation.
  • Hardcoded hierarchy: Phase hierarchy is defined in ActivePerformanceTracker for report display only. Call sites use flat phase names; the tracker maps them to the hierarchy.
  • Phase constants: All phase names are public static final String on PerformanceTracker interface, imported via static imports — no string literals at call sites.
  • Tracking inside methods: startPhase/endPhase calls live inside each method (e.g., createJavaClassSource, appendFields) rather than wrapping calls in buildClassSource, improving readability.

Usage

Enable performance tracking via compiler argument:

mvn -pl processor -am install -DskipTests
mvn -pl example clean compile -Asimplebuilder.performanceTracking=true

Out of Scope (Follow-up PR)

  • 1000 DTO test classes for the performance-test module
  • Performance measurement runs and results documentation

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
48.6% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

* Extraction")
* @param className the simple name of the class being processed
*/
void startPhase(String phase, String className);
* Extraction")
* @param className the simple name of the class being processed
*/
void startPhase(String phase, String className);
*
* @param generatorName the simple class name of the method generator
*/
void startGenerator(String generatorName);
*
* @param enhancerName the simple class name of the builder enhancer
*/
void startEnhancer(String enhancerName);
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Patch % Lines
...r/processing/logging/ActivePerformanceTracker.java 0.00% 146 Missing ⚠️
...rs/simple/builders/processor/BuilderProcessor.java 96.42% 0 Missing and 1 partial ⚠️
...ilders/processor/processing/ProcessingContext.java 85.71% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

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.

2 participants