What does a JMeter JSR223 element's 'Cache compiled script if available' checkbox actually do?
answer
- One switch, two very different code paths
- Compile once instead of every call
- Keyed on the script text itself
- Bounded by a jmeter.properties size
basics
~20 sIt lets JMeter compile the inline Script once and reuse the compiled form instead of handing the source to the engine on every execution. It only bites if the engine implements javax.script.Compilable, as Groovy does.
solid answer
~40 sThe checkbox governs the **inline Script text** of a JSR223 element. With it ticked and an engine that implements `javax.script.Compilable`, JMeter compiles the script text once, stores the resulting `CompiledScript` in a process-wide cache keyed on the MD5 digest of that text, and evaluates the compiled form on every later execution. Untick it and the raw source is passed to `ScriptEngine.eval` every single time. A **Script File** is a separate path in the code and is compiled and cached regardless of the checkbox, keyed on language plus absolute path plus the file's last-modified time. The cache is bounded by the `jsr223.compiled_scripts_cache_size` property, which defaults to 100, and is emptied when the test ends. The manual's warning matters: a cached script must not contain JMeter variable or function references.
code
properties · 3 lines# Used by JSR-223 elements
# Size of compiled scripts cache
#jsr223.compiled_scripts_cache_size=100go deeper
Know that the box exists, that it is ticked by default on a new element, and that Groovy is the language it helps. Leaving it alone is the right default.
Explain the mechanism: compile once, key the cached CompiledScript on the MD5 of the script text, and fall back to plain eval when the engine is not Compilable.
Be ready to say why a cached element must not carry JMeter variable or function references in its script text, and what you change instead of unticking the box.
Decide the team rule that keeps this from being a per-element judgement call: scripts in files, values through the bound context, and a cache size chosen for the plans you actually run.
## What the checkbox controls The field is stored in the plan as `<stringProp name="cacheKey">`, and in Apache JMeter 6.0.0 the GUI renders it as a checkbox labelled **Cache compiled script if available**, inside a group called *Script compilation caching*. The value is still a string: JMeter treats anything other than the literal `false` as "on". When a JSR223 element runs, it takes one of two paths: - **Inline Script text.** If the engine implements `javax.script.Compilable` *and* the checkbox is not set to `false`, JMeter compiles the script and caches the `CompiledScript` under the MD5 digest of the script text. Otherwise it calls `ScriptEngine.eval(script, bindings)` on the raw source every time. - **Script File.** The checkbox is not consulted at all. If the engine is `Compilable`, the file is compiled and cached; if not, the file is read and evaluated directly. The manual says this plainly: *"Use Script files instead of inlining them. This will make JMeter compile them if this feature is available on ScriptEngine and cache them."* BeanShell's engine is a special case in the source: it declares `Compilable` but throws when asked to compile, so JMeter excludes `bsh.engine.BshScriptEngine` by class name and always evaluates it directly. ## The two cache keys | Source | Cache key | Checkbox consulted? | |---|---|---| | inline `Script` text | MD5 digest of the script text | yes — `false` disables caching | | `Script File` | language + absolute path + file last-modified time | no — always cached when compilable | The file key carrying `lastModified` is why editing a script file between runs picks up the new content without restarting JMeter: a changed timestamp is a different key. ## Size, lifetime and the property The cache is a single process-wide Caffeine cache shared by every JSR223 element and every thread. Its bound comes from a JMeter property: ```properties # Used by JSR-223 elements # Size of compiled scripts cache #jsr223.compiled_scripts_cache_size=100 ``` That line ships commented out in `bin/jmeter.properties`, so the effective default of 100 comes from the code, not the file. Because the cache is keyed by content rather than by element, two elements holding byte-identical scripts share one compiled entry. When the test ends, the whole cache is invalidated. ## When the box has to be cleared The manual's note is the operative rule: *"ensure your script code does not use JMeter variables or JMeter function calls directly in script code as caching would only cache first replacement."* JMeter substitutes `${...}` into the inline script before the engine sees it, but the element computes its cache digest once and never recomputes it, so the compiled artefact freezes the first substitution. If the script text must contain a reference JMeter resolves, either untick the box or — far better — take the value from the bound context at run time instead, which keeps the script text constant and cacheable. One more consequence of caching being on by default: JMeter's manual also advises setting `-Dgroovy.use.classvalue=true` when running Groovy *without* the box ticked, citing a Groovy memory leak reported against version 2.4.6. ## Reading it in a plan file A ticked box, a legacy plan and an explicitly disabled element look like this respectively: ```xml <stringProp name="cacheKey">true</stringProp> <stringProp name="cacheKey">c430f36f-ade7-439d-ac9f-7cc0a9cb5a38</stringProp> <stringProp name="cacheKey">false</stringProp> ``` The middle one is a plan written when the field held a generated unique string; JMeter 6.0.0 reads it as enabled, because only the exact text `false` turns caching off. That history also explains a wrinkle in the manual: only the JSR223 Sampler section describes the field as a checkbox, while all five other sections — JSR223 PreProcessor, PostProcessor, Assertion, Timer and Listener — still describe it as a "Unique String across Test Plan".
- Does ticking 'Cache compiled script if available' change anything for a JMeter JSR223 element that uses a Script File?No. The file path is handled before the checkbox is ever read: if the engine implements `Compilable`, the file is compiled and cached regardless, keyed on language, absolute path and last-modified time. The checkbox only governs the inline `Script` text area.
- Two JMeter JSR223 elements in one plan hold exactly the same script text. How many compiled scripts are cached?One. The inline-script cache key is the MD5 digest of the script text, and the cache is a single process-wide store shared by all JSR223 elements and threads, so byte-identical scripts collapse to one entry. Change one character in either and they become two.
saying these in an interview costs you the question
- Thinks the checkbox caches the script's result rather than its compiled form
- Believes caching works for every scripting language
- Says a Script File needs the box ticked to be cached
- Assumes the cache survives the end of the test
- Treats an empty cacheKey property as caching disabled