This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git

commit 9e2e2bcbd13d128c0d887a23e67e2e7a9dcf9355
Author: Felix Schumacher <[email protected]>
AuthorDate: Wed Sep 25 12:28:54 2024 +0200

    Add startTime to AbstractThreadGroup and use it in OMTG and 
PreciseThroughputTimer
    
    A thread group might start later than the test. When we calculate delays on 
the start time of
    the test, we might get a stampede of samples run at the start of the thread 
group.
---
 .../poissonarrivals/PreciseThroughputTimer.java      |  4 ++--
 .../apache/jmeter/engine/StandardJMeterEngine.java   |  1 +
 .../apache/jmeter/threads/AbstractThreadGroup.java   | 20 ++++++++++++++++++++
 .../jmeter/threads/openmodel/OpenModelThreadGroup.kt |  2 +-
 xdocs/changes.xml                                    |  4 +++-
 5 files changed, 27 insertions(+), 4 deletions(-)

diff --git 
a/src/components/src/main/java/org/apache/jmeter/timers/poissonarrivals/PreciseThroughputTimer.java
 
b/src/components/src/main/java/org/apache/jmeter/timers/poissonarrivals/PreciseThroughputTimer.java
index 4864e22117..ee4998a62c 100644
--- 
a/src/components/src/main/java/org/apache/jmeter/timers/poissonarrivals/PreciseThroughputTimer.java
+++ 
b/src/components/src/main/java/org/apache/jmeter/timers/poissonarrivals/PreciseThroughputTimer.java
@@ -99,7 +99,7 @@ public class PreciseThroughputTimer extends 
AbstractTestElement implements Clone
             nextEvent = events.next();
         }
         long now = System.currentTimeMillis();
-        long testStarted = JMeterContextService.getTestStartTime();
+        long testStarted = 
JMeterContextService.getContext().getThreadGroup().getStartTime();
         long delay = (long) (nextEvent * TimeUnit.SECONDS.toMillis(1) + 
testStarted - now);
         if (log.isDebugEnabled()) {
             log.debug("Calculated delay is {}", delay);
@@ -117,7 +117,7 @@ public class PreciseThroughputTimer extends 
AbstractTestElement implements Clone
     }
 
     private EventProducer getEventProducer() {
-        long testStarted = JMeterContextService.getTestStartTime();
+        long testStarted = 
JMeterContextService.getContext().getThreadGroup().getStartTime();
         long prevStarted = PREV_TEST_STARTED.get();
         if (prevStarted != testStarted && 
PREV_TEST_STARTED.compareAndSet(prevStarted, testStarted)) {
             // Reset counters if we are calculating throughput for a new test, 
see https://github.com/apache/jmeter/issues/6165
diff --git 
a/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java 
b/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
index a72602fb2e..618f5b9212 100644
--- a/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
+++ b/src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java
@@ -574,6 +574,7 @@ public class StandardJMeterEngine implements JMeterEngine, 
Runnable {
             threadGroupTree.add(group, testLevelElements);
 
             groups.add(group);
+            group.setStartTime(System.currentTimeMillis());
             group.start(groupCount, notifier, threadGroupTree, this);
         } catch (JMeterStopTestException ex) { // NOSONAR Reported by log
             JMeterUtils.reportErrorToUser("Error occurred starting thread 
group :" + group.getName()+ ", error message:"+ex.getMessage()
diff --git 
a/src/core/src/main/java/org/apache/jmeter/threads/AbstractThreadGroup.java 
b/src/core/src/main/java/org/apache/jmeter/threads/AbstractThreadGroup.java
index 37b3f104b2..63a4462a4d 100644
--- a/src/core/src/main/java/org/apache/jmeter/threads/AbstractThreadGroup.java
+++ b/src/core/src/main/java/org/apache/jmeter/threads/AbstractThreadGroup.java
@@ -21,6 +21,7 @@ import java.io.Serializable;
 import java.time.Duration;
 import java.util.IdentityHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.jmeter.control.Controller;
 import org.apache.jmeter.control.IteratingController;
@@ -86,6 +87,8 @@ public abstract class AbstractThreadGroup extends 
AbstractTestElement
 
     private final AtomicInteger numberOfThreads = new AtomicInteger(0); // 
Number of active threads in this group
 
+    private final AtomicLong startTime = new AtomicLong(0);
+
     @Override
     public AbstractThreadGroupSchema getSchema() {
         return AbstractThreadGroupSchema.INSTANCE;
@@ -97,6 +100,23 @@ public abstract class AbstractThreadGroup extends 
AbstractTestElement
         return new PropertiesAccessor<>(this, getSchema());
     }
 
+    /**
+     * Get the time when this thread group has been started
+     * @return time in milliseconds since epoch
+     */
+    public long getStartTime() {
+        return startTime.get();
+    }
+
+    /**
+     * Set the time when this thread group has been started.<br>
+     * Will probably be set by StandardJMeterEngine.
+     * @param startTime time in milliseconds since epoch
+     */
+    public void setStartTime(long startTime) {
+        this.startTime.set(startTime);
+    }
+
     /** {@inheritDoc} */
     @Override
     public boolean isDone() {
diff --git 
a/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/OpenModelThreadGroup.kt
 
b/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/OpenModelThreadGroup.kt
index 5948dc6d40..45c0f6cef6 100644
--- 
a/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/OpenModelThreadGroup.kt
+++ 
b/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/OpenModelThreadGroup.kt
@@ -204,7 +204,7 @@ public class OpenModelThreadGroup :
             val seed = randomSeed
             val rnd = if (seed == 0L) Random() else Random(seed)
             val gen = ThreadScheduleProcessGenerator(rnd, parsedSchedule)
-            val testStartTime = System.currentTimeMillis()
+            val testStartTime = this.startTime
             val executorService = Executors.newCachedThreadPool()
             this.executorService = executorService
             val starter = ThreadsStarter(testStartTime, executorService, 
activeThreads, gen) { threadNumber ->
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 60836279fd..025af48bca 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -57,7 +57,7 @@ JMeter 6.x requires Java 17 or later for execution (Java 21 
is recommended).
 Summary
 </p>
 <ul>
-<li><a href="#Bug fixes">Bug fixes</a></li>
+<li><a href="#Changes">Changes</a></li>
 </ul>
 
   <ch_section>Changes</ch_section>
@@ -65,6 +65,8 @@ Summary
   <ul>
     <li><pr>6220</pr> Require Java 17 or later for running JMeter</li>
     <li><pr>6274</pr> Change references to old MySQL driver to new class 
<code>com.mysql.cj.jdbc.Driver</code></li>
+    <li><issue>6352</issue> Calculate delays in Open Model Thread Group and 
Precise Throughput
+        Timer relative to start of Thread Group instead of the start of the 
test.</li>
   </ul>
 
  <!--  =================== Thanks =================== -->

Reply via email to