This guide covers the performance features, caching system, and optimization techniques used by the OpenAPI Model Generator plugin.
- Performance Overview
- Multi-Level Caching System
- Parallel Processing
- Incremental Builds
- Template Performance
- Performance Metrics
- Configuration for Performance
- Troubleshooting Performance
- Best Practices
The OpenAPI Model Generator plugin is designed for enterprise-scale performance with multiple optimization layers:
- 90% faster no-change builds through comprehensive caching
- 70% faster incremental builds with change detection
- Thread-safe parallel processing for multi-spec projects
- Cross-build performance optimization with global cache persistence
- Lazy evaluation and selective processing
The plugin implements a sophisticated three-tier caching system:
Purpose: Eliminates redundant template extractions within single build execution
Scope: Single Gradle daemon session
Benefits:
- Prevents re-extracting identical templates multiple times during a build
- Shared across all specs in a multi-spec project
- Thread-safe using ConcurrentHashMap
Implementation:
// Session cache key: generator + version + template name
String cacheKey = String.format("%s-%s-%s", generatorName, generatorVersion, templateName);Purpose: SHA-256 content validation for reliable template change detection
Scope: Individual spec working directories
Location: build/template-work/{generator}-{specName}/
Benefits:
- Validates template content hasn't changed since last extraction
- Enables incremental template processing
- Prevents unnecessary re-extraction when templates are identical
Implementation:
- SHA-256 hashes stored for each template file
- Content validation before reusing cached templates
- Automatic invalidation when source templates change
Purpose: Cross-build performance with persistent caching
Scope: Global across all projects and builds
Location: ~/.gradle/caches/openapi-modelgen/
Benefits:
- 90% faster no-change builds
- 70% faster incremental builds
- Shared between different projects using the same generator/version
- Survives Gradle daemon restarts
Cache Structure:
~/.gradle/caches/openapi-modelgen/
├── templates/
│ └── {generator}-{version}/
│ ├── {template-name}.mustache
│ └── {template-name}.mustache.sha256
├── customizations/
│ └── {customization-hash}/
│ └── processed-customization.yaml
└── metadata/
└── cache-info.json
The caching system uses comprehensive invalidation based on:
- OpenAPI Generator version: Different versions have different templates
- Plugin version: Plugin updates may change processing logic
- Specification content: SHA-256 hash of OpenAPI spec files
- Template content: SHA-256 hash of template files
- Customization content: SHA-256 hash of YAML customization files
- Configuration changes: Plugin configuration affecting generation
Configuration:
openapiModelgen {
defaults {
parallel true // Enable parallel processing (default)
}
}Benefits:
- Concurrent generation of multiple specifications
- Scales with available CPU cores
- Independent working directories prevent cross-contamination
Implementation Details:
- Each spec gets isolated working directory:
build/template-work/{generator}-{specName}/ - Thread-safe caching using ConcurrentHashMap
- Parallel task execution using Gradle's parallel capabilities
- No shared mutable state between spec generations
Disable parallel processing if needed:
openapiModelgen {
defaults {
parallel false // Disable for debugging or resource constraints
}
}Command line override:
./gradlew generateAllModels --no-parallelThe plugin implements sophisticated change detection:
Input Tracking:
- OpenAPI specification files (SHA-256 hash)
- Template files (SHA-256 hash)
- YAML customization files (SHA-256 hash)
- Plugin configuration (serialized hash)
- OpenAPI Generator version
Output Tracking:
- Generated model files
- Generated test files
- Generated documentation
Gradle Integration:
- Uses
@InputFiles,@OutputDirectoryannotations - Leverages Gradle's incremental build system
- Only regenerates when inputs actually change
SHA-256 Hashing:
// Example: Template content validation
String templateContent = Files.readString(templatePath);
String currentHash = DigestUtils.sha256Hex(templateContent);
String cachedHash = Files.readString(hashFile);
if (!currentHash.equals(cachedHash)) {
// Template changed - invalidate cache and regenerate
extractAndProcess(templatePath);
Files.writeString(hashFile, currentHash);
}Template Extraction:
- Templates extracted only at execution time
- Deferred until actually needed for generation
- Reduces configuration time overhead
Customization Processing:
- YAML customizations processed only when templates require them
- Cached results reused across builds
- Selective processing based on template dependencies
Only processes templates that require customization:
- Automatic detection of templates with YAML customizations
- Recursive discovery of template dependencies
- Skips templates without any modifications
Template Dependency Discovery:
// Parses templates for {{>templateName}} references
Pattern includePattern = Pattern.compile("\\{\\{>\\s*(\\w+)\\s*\\}\\}");
Matcher matcher = includePattern.matcher(templateContent);
while (matcher.find()) {
String dependentTemplate = matcher.group(1);
extractTemplateDependency(dependentTemplate);
}Early Detection:
- Identifies explicit user templates during configuration
- Skips unnecessary YAML processing when user templates exist
- Optimizes template resolution hierarchy
Smart Customization Skipping:
- Automatically skips plugin customizations when user customizations exist
- Reduces processing overhead for overridden templates
- Maintains correct precedence while optimizing performance
High-Performance Template Caching:
- Global persistence in
~/.gradle/caches/openapi-modelgen/ - Metadata tracking for version compatibility
- Cross-build persistence for maximum reuse
Cache Organization:
~/.gradle/caches/openapi-modelgen/templates/
├── spring-7.14.0/
│ ├── pojo.mustache
│ ├── pojo.mustache.sha256
│ ├── enumClass.mustache
│ └── enumClass.mustache.sha256
└── java-7.14.0/
├── model.mustache
└── model.mustache.sha256
No-Change Builds: 90% faster
- Cold start: ~15 seconds
- With caching: ~1.5 seconds
- Improvement: 90% reduction in build time
Incremental Builds: 70% faster
- Without caching: ~8 seconds
- With caching: ~2.4 seconds
- Improvement: 70% reduction in build time
Parallel vs Sequential:
- 4 specs sequential: ~20 seconds
- 4 specs parallel: ~6 seconds
- Improvement: 70% reduction with 4-core machine
Template Sharing:
- Templates shared between specs using same generator
- Memory usage scales sub-linearly with spec count
- Efficient garbage collection with weak references
Cache Memory Management:
- LRU eviction for session caches
- Configurable cache size limits
- Automatic cleanup of stale cache entries
openapiModelgen {
defaults {
// Enable all performance features
parallel true // Parallel multi-spec processing
applyPluginCustomizations true // Use optimized built-in customizations
// Minimize validation overhead for trusted specs
validateSpec false // Skip validation for known-good specs
// Disable features you don't need
generateModelTests false // Skip test generation if not needed
generateApiDocumentation false // Skip documentation if not needed
saveOriginalTemplates false // Don't save originals unless debugging
// Optimize template processing
templatePrecedence([
'user-templates', // Most specific first
'user-customizations',
'plugin-customizations',
'openapi-generator'
])
}
}High Performance (minimal features):
openapiModelgen {
defaults {
parallel true
validateSpec false
generateModelTests false
generateApiDocumentation false
saveOriginalTemplates false
applyPluginCustomizations true
}
}Balanced (good performance with useful features):
openapiModelgen {
defaults {
parallel true
validateSpec true // Keep validation for safety
generateModelTests true // Generate tests
generateApiDocumentation false // Skip docs for performance
saveOriginalTemplates false // No debugging overhead
applyPluginCustomizations true
}
}Full Features (some performance impact):
openapiModelgen {
defaults {
parallel true // Keep parallel processing
validateSpec true
generateModelTests true
generateApiDocumentation true
generateModelDocumentation true
saveOriginalTemplates true // Enable for debugging
applyPluginCustomizations true
}
}Enable debug logging:
./gradlew generateAllModels --debug --profileCheck cache usage:
# View cache directory
ls -la ~/.gradle/caches/openapi-modelgen/
# Check cache sizes
du -sh ~/.gradle/caches/openapi-modelgen/*Profile build performance:
./gradlew generateAllModels --profile
# Check build/reports/profile/ for detailed timingSlow first build:
- Cause: Cache population
- Solution: Normal behavior, subsequent builds will be faster
- Workaround: Pre-populate cache with
./gradlew generateAllModels --dry-run
Slow incremental builds:
- Cause: Cache invalidation due to changing inputs
- Solution: Check if specs/templates are actually changing
- Debug: Enable
--infologging to see what's being regenerated
Memory issues with many specs:
- Cause: Too many concurrent template extractions
- Solution: Disable parallel processing temporarily
- Workaround:
./gradlew generateAllModels --no-parallel
Cache corruption:
- Symptoms: Inconsistent generation results
- Solution: Clear cache and regenerate
- Command:
rm -rf ~/.gradle/caches/openapi-modelgen/
Clear global cache:
rm -rf ~/.gradle/caches/openapi-modelgen/Clear project cache:
./gradlew clean
rm -rf build/template-work/Inspect cache contents:
# View cached templates
find ~/.gradle/caches/openapi-modelgen/ -name "*.mustache" | head -10
# Check cache metadata
cat ~/.gradle/caches/openapi-modelgen/metadata/cache-info.json-
Organize specs efficiently:
src/main/resources/openapi-spec/ ├── pets.yaml ├── orders.yaml └── users.yaml -
Use stable spec names:
specs { pets { /* stable name */ } orders { /* stable name */ } }
-
Minimize template customizations:
- Use YAML customizations instead of complete template overrides
- Share customizations via template libraries
- Keep customizations focused and minimal
-
Enable parallel processing:
openapiModelgen { defaults { parallel true // Always enable unless debugging } }
-
Use appropriate validation:
openapiModelgen { defaults { validateSpec true // Enable for development } specs { production { validateSpec false // Disable for trusted production specs } } }
-
Configure CI/CD appropriately:
# CI builds - maximize performance ./gradlew generateAllModels --parallel --no-validate-spec # Development builds - keep validation ./gradlew generateAllModels --parallel
-
Use YAML customizations:
- Faster processing than complete template overrides
- Better caching efficiency
- Easier to maintain
-
Minimize template dependencies:
- Reduce the number of included templates
- Use self-contained customizations where possible
-
Test performance impact:
# Measure before time ./gradlew clean generateAllModels # Measure after changes time ./gradlew clean generateAllModels # Compare incremental builds time ./gradlew generateAllModels # Should be very fast
-
Monitor cache growth:
# Check cache size periodically du -sh ~/.gradle/caches/openapi-modelgen/
-
Clean up old caches:
# Clean caches older than 30 days find ~/.gradle/caches/openapi-modelgen/ -type f -mtime +30 -delete
-
Profile builds regularly:
./gradlew generateAllModels --profile # Review build/reports/profile/ for performance regressions
By following these performance guidelines, you can achieve optimal build times while maintaining the full feature set of the OpenAPI Model Generator plugin.