Skip to content

perf(runtime): cache the interface class of chain link sources per class (3.4.x) - #702

Merged
lukaszlenart merged 1 commit into
ognl-3-4-xfrom
perf/cache-interface-class-34x
Oct 8, 2026
Merged

lukaszlenart merged 1 commit into
ognl-3-4-xfrom
perf/cache-interface-class-34x

Conversation

@lukaszlenart

Copy link
Copy Markdown
Collaborator

Backport of #655 to the 3.4.x line. Refs #650

ASTChain asks ASTProperty.getIndexedPropertyType() about every link of a property chain except the last, and that calls OgnlExpressionCompiler.getInterfaceClass(source.getClass()). The default compiler walks the class's interface hierarchy each time, although the answer only depends on the class.

Change

  • New ClassCache in OgnlCache, created by the cache factory like the other per-class caches; its entry factory calls the current compiler's getInterfaceClass.
  • New package-private OgnlRuntime.getInterfaceClass(Class) reads it; the two call sites in ASTProperty use it.
  • OgnlCache.clear() clears it, so clearCache() and clearAdditionalCache() both drop it.
  • It honours the ClassCacheInspector.
  • setCompiler(...) clears it, because the cached values are answers of the previous compiler.

Differences from #655

  • OgnlRuntimeInterfaceClassCacheTest drops the generic type parameters of ExpressionCompiler / OgnlExpressionCompiler, which aren't generic on this branch.
  • OgnlPropertyChainPerformanceBenchmarks isn't ported: this branch has no benchmarks module.

Tests

  • Before the cache was added, with getInterfaceClass delegating straight to the compiler, 3 of the 6 new tests failed (a 5× evaluated chain asked the compiler 5 times instead of once). With the cache, all 6 pass and appear in target/surefire-reports.
  • ./mvnw clean test: 1190 tests, 0 failures.

🤖 Generated with Claude Code

Backport of #655 to the 3.4.x line.

ASTChain asks ASTProperty.getIndexedPropertyType() about every link of a
property chain except the last one, and that calls
OgnlExpressionCompiler.getInterfaceClass(source.getClass()). The default
compiler copies the class's interface array and walks its hierarchy each
time, although the answer only depends on the class.

Add a ClassCache for it in OgnlCache, read through the new package-private
OgnlRuntime.getInterfaceClass(Class), and use it from the two call sites in
ASTProperty. OgnlCache.clear() drops it, it honours the ClassCacheInspector,
and setCompiler() clears it since the cached values are answers of the
previous compiler.

The test drops the generic type parameters of ExpressionCompiler, which are
not generic on this branch. The JMH benchmark from #655 is not ported, as
this branch has no benchmarks module.

Refs #650

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lukaszlenart
lukaszlenart marked this pull request as ready for review October 8, 2026 16:16
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit eb94161 into ognl-3-4-x Oct 8, 2026
6 checks passed
@lukaszlenart
lukaszlenart deleted the perf/cache-interface-class-34x branch October 8, 2026 16:19
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.

1 participant