[ 
https://issues.apache.org/jira/browse/CAMEL-24682?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18114154#comment-18114154
 ] 

Federico Mariani commented on CAMEL-24682:
------------------------------------------

Draft PR: https://github.com/apache/camel/pull/26303

_Claude Code on behalf of Croway_

> camel-groovy - Resolve the language and GroovyShellFactory once, keep the 
> compiled script per expression, build the binding lazily
> ----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24682
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24682
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-groovy
>    Affects Versions: 4.22.0
>            Reporter: Federico Mariani
>            Assignee: Federico Mariani
>            Priority: Major
>             Fix For: 4.23.0
>
>
> Every evaluation of a groovy expression does work that only needs doing once:
> * {{GroovyExpression.instantiateScript}} calls {{resolveLanguage("groovy")}} 
> and {{registry.findByType(GroovyShellFactory.class)}} on every exchange 
> (GroovyExpression.java:70-71). {{findByType}} scans every bean in the 
> registry, so with 500 unrelated beans one evaluation is 11.8x slower (3.36 M 
> -> 0.28 M ops/s).
> * The binding is rebuilt on every evaluation: a globals map, a copy of it, 
> {{ExchangeHelper.populateVariableMap}} (which copies all exchange properties 
> through {{getAllProperties()}}), a {{DefaultAttachmentMessage}} and a 
> {{Binding}}. That is ~154 ns and 1,152 B of a ~297 ns evaluation and 78% of 
> the bytes it allocates.
> * The compiled script class goes through the shared 1,000-entry language 
> cache on every evaluation; a script evicted from it is recompiled (0.70 ms 
> and 480 KB per evaluation past 1,000 distinct scripts; a 5-minute load with 
> 1,500 distinct scripts ran at 5,019 msg/s with 600,000 classes loaded).
> * The {{Script}} instance is created through {{ObjectHelper.newInstance}}, 
> which copies the {{Constructor}} on every call.
> Measured on main (JDK 21): {{body + '-' + header.foo}} at 3.0 M ops/s against 
> 47.8 M for a Java expression; the route {{filter(amount > 100) -> 
> setBody(concat)}} at 0.48x the Java route on one thread and 0.22x on eight; a 
> 5-minute 8-thread load at 1.08 M msg/s (0.26x Java) with a p99 of 102 us.
> Proposed fix (implemented and benchmarked): resolve the language and the 
> shell factory once per CamelContext; keep the compiled class in the 
> {{Expression}} (checked against context, language and a generation counter 
> bumped on language stop and dev-mode reload, so the shared cache no longer 
> removes classes on eviction); a lazy {{ExchangeBinding}} that snapshots 
> {{in}}, {{body}}, {{headers}}, {{exception}}, {{out}} and materializes 
> {{exchangeProperties}}, {{variables}} and {{attachments}} on first access; a 
> cached constructor {{MethodHandle}}.
> With the fix: expressions 4.9-7.7x faster, route 0.94x the Java route on 1 
> and 8 threads, load 3.80 M msg/s (0.91x Java) with a p99 of 3 us and the same 
> 26 MB heap after GC, 1,500 distinct scripts 2.92 M msg/s.
> Behaviour changes that need an upgrade guide entry: a {{GroovyShellFactory}} 
> bound to the registry after the first evaluation is no longer picked up; 
> {{exchangeProperties}}, {{variables}} and {{attachments}} are read on first 
> access rather than when the binding is created. Protected {{createBinding}} / 
> {{instantiateScript}} signatures are kept.
> Related: CAMEL-8259 (origin of the per-evaluation factory lookup), 
> CAMEL-21212, CAMEL-21717, CAMEL-21755 (binding variables).
> ----
> _Found during a benchmark review of camel-groovy and the other scripting 
> languages (camel-performance-tests branch camel-groovy-perf, 
> tests/camel-jmh/groovy-results, JMH 1.37, JDK 21, one M1 Pro laptop). A 
> candidate fix with tests exists on the local apache/camel branch 
> camel-perf-all-fixes; a PR follows._
> _Claude Code on behalf of Croway_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to