diff --git a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java index 35f94b26982..b36bef0abcc 100644 --- a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java +++ b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java @@ -19,7 +19,9 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -92,6 +94,8 @@ public class JMeterThread implements Runnable, Interruptible { private final HashTree testTree; + private final Map> parentControllersCache = new HashMap<>(); + private final TestCompiler compiler; private final JMeterThreadMonitor monitor; @@ -343,6 +347,20 @@ public void run() { } } + private static class CachedPathToRootTraverser extends FindTestElementsUpToRootTraverser { + private final List controllers; + + CachedPathToRootTraverser(List controllers) { + super(null); + this.controllers = controllers; + } + + @Override + public List getControllersToRoot() { + return controllers; + } + } + /** * Trigger break/continue/switch to next thread Loop depending on consumer implementation * @param sampler Sampler Base sampler @@ -363,8 +381,16 @@ private void triggerLoopLogicalActionOnParentControllers(Sampler sampler, JMeter (sampler != null ? sampler.getName() : "null") + ", sampler:" + sampler); } // Find parent controllers of current sampler - FindTestElementsUpToRootTraverser pathToRootTraverser = new FindTestElementsUpToRootTraverser(realSampler); - testTree.traverse(pathToRootTraverser); + List controllers = parentControllersCache.get(realSampler); + FindTestElementsUpToRootTraverser pathToRootTraverser; + if (controllers == null) { + pathToRootTraverser = new FindTestElementsUpToRootTraverser(realSampler); + testTree.traverse(pathToRootTraverser); + controllers = pathToRootTraverser.getControllersToRoot(); + parentControllersCache.put(realSampler, controllers); + } else { + pathToRootTraverser = new CachedPathToRootTraverser(controllers); + } consumer.accept(pathToRootTraverser);