Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions performance-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.github.java-helpers</groupId>
<artifactId>simple-builders-performance-test</artifactId>
<version>0.6.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Simple Builders - Performance Test</name>
<description>Performance test module with 1000 DTO classes for measuring builder generation performance. Not part of the default build.</description>
<url>https://github.com/java-helpers/simple-builders</url>
<inceptionYear>2026</inceptionYear>

<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<commons-lang.version>3.20.0</commons-lang.version>

<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>

<!-- Performance tracking disabled by default; enable with -Asimplebuilder.performanceTracking=true -->
<simplebuilder.performanceTracking>false</simplebuilder.performanceTracking>
<simplebuilder.verbose>false</simplebuilder.verbose>

<plugin.maven.compiler.version>3.15.0</plugin.maven.compiler.version>
<plugin.maven.deploy.version>3.1.4</plugin.maven.deploy.version>
</properties>

<dependencies>
<dependency>
<groupId>io.github.java-helpers</groupId>
<artifactId>simple-builders-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- Skip deployment for this module -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${plugin.maven.deploy.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.version}</release>
<generatedSourcesDirectory>${project.basedir}/generated-performance-builder</generatedSourcesDirectory>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.github.java-helpers</groupId>
<artifactId>simple-builders-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Averbose=${simplebuilder.verbose}</arg>
<arg>-Asimplebuilder.performanceTracking=${simplebuilder.performanceTracking}</arg>
</compilerArgs>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<configuration>
<proc>none</proc>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,5 +172,11 @@
</build>
<!-- Other configuration moved to individual modules -->
</profile>
<profile>
<id>performance-test</id>
<modules>
<module>performance-test</module>
</modules>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@

import static org.javahelpers.simple.builders.processor.model.core.BuilderToGenerationTypeMapper.toRenderingDto;
import static org.javahelpers.simple.builders.processor.processing.BuilderDefinitionCreator.extractFromElement;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_BUILDER_DEFINITION_EXTRACTION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_CODE_GENERATION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_CONFIGURATION_RESOLUTION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_DTO_MAPPING;

import com.google.auto.service.AutoService;
import java.util.ArrayList;
Expand Down Expand Up @@ -56,7 +60,8 @@
import org.javahelpers.simple.builders.processor.processing.CompilerArgumentsEnum;
import org.javahelpers.simple.builders.processor.processing.CompilerArgumentsReader;
import org.javahelpers.simple.builders.processor.processing.ProcessingContext;
import org.javahelpers.simple.builders.processor.processing.ProcessingLogger;
import org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker;
import org.javahelpers.simple.builders.processor.processing.logging.ProcessingLogger;

/**
* BuilderProcessor is an annotation processor for execution in generate-sources phase. The
Expand All @@ -83,7 +88,8 @@ public synchronized void init(ProcessingEnvironment processingEnv) {
logger.debug("Loaded global configuration from compiler arguments: %s", globalConfig);

this.context = new ProcessingContext(logger, globalConfig, processingEnv);
this.codeGenerator = new RoasterCodeGenerator(processingEnv, logger);
this.codeGenerator =
new RoasterCodeGenerator(processingEnv, logger, context.getPerformanceTracker());
this.jacksonModuleGenerator = new JacksonModuleGenerator(processingEnv, logger);

// Initialize GeneratorRegistry once during processor initialization
Expand Down Expand Up @@ -112,6 +118,10 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment

// Generate Jackson Module if processing is over and feature is enabled
if (roundEnv.processingOver()) {
// Generate performance report at the end of processing
PerformanceTracker tracker = context.getPerformanceTracker();
tracker.generateReport(context.getLogger());

List<GenerationTargetClassDto> moduleClassDefs =
jacksonModuleGenerator.getModuleDefinitions();
for (GenerationTargetClassDto moduleClassDef : moduleClassDefs) {
Expand Down Expand Up @@ -175,13 +185,17 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
.sorted(Comparator.comparing(element -> element.getSimpleName().toString()))
.toList();

PerformanceTracker tracker = context.getPerformanceTracker();
int successfulGenerations = 0;
for (Element annotatedElement : sortedElements) {
context.debugStartOperation("Processing element: " + annotatedElement.getSimpleName());
String className = annotatedElement.getSimpleName().toString();
tracker.startClass(className);
try {
// Resolve configuration per-element to handle all layers
// (defaults, global, template, inline)
// Track Configuration Resolution (actual work happens here)
tracker.startPhase(PHASE_CONFIGURATION_RESOLUTION, className);
BuilderConfiguration config = reader.resolveConfiguration(annotatedElement);
tracker.endPhase(PHASE_CONFIGURATION_RESOLUTION);
context.debug("Configuration resolved: %s", config);
process(annotatedElement, config);
successfulGenerations++;
Expand Down Expand Up @@ -225,14 +239,46 @@ public SourceVersion getSupportedSourceVersion() {
private void process(Element annotatedElement, BuilderConfiguration config)
throws BuilderException {
context.initConfigurationForProcessingTarget(config);
PerformanceTracker tracker = context.getPerformanceTracker();
String className = annotatedElement.getSimpleName().toString();

// Track Builder Definition Extraction
tracker.startPhase(PHASE_BUILDER_DEFINITION_EXTRACTION, className);
BuilderDefinitionDto builderDef = extractFromElement(annotatedElement, context);
tracker.endPhase(PHASE_BUILDER_DEFINITION_EXTRACTION);

// Compute class-level metrics now that the definition is available
int fieldCount = builderDef.getAllFieldsForBuilder().size();
int collectionCount =
(int)
builderDef.getAllFieldsForBuilder().stream()
.filter(
f -> {
String typeName = f.getFieldType().getFullQualifiedName();
return typeName.startsWith("java.util.List")
|| typeName.startsWith("java.util.Set")
|| typeName.startsWith("java.util.Map")
|| typeName.startsWith("java.util.Collection");
})
.count();

// Track DTO Mapping
tracker.startPhase(PHASE_DTO_MAPPING, className);
GenerationTargetClassDto renderingDto = toRenderingDto(builderDef);
tracker.endPhase(PHASE_DTO_MAPPING);

// Track Code Generation (parent phase; sub-phases tracked inside RoasterCodeGenerator)
tracker.startPhase(PHASE_CODE_GENERATION, className);
codeGenerator.generateClass(renderingDto);
tracker.endPhase(PHASE_CODE_GENERATION);

// Collect info for Jackson Module if enabled
jacksonModuleGenerator.addEntry(builderDef, annotatedElement);
context.debug("Jackson module entry added");

// End class-level timing (started in caller before config resolution)
tracker.endClass(fieldCount, collectionCount);

// Add summary of what was generated
context.debugEndOperation(
"Generated builder with %d fields and %d methods for %s",
Expand Down
Loading
Loading