Skip to content

Commit 9e2e2bc

Browse files
committed
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.
1 parent 45996db commit 9e2e2bc

5 files changed

Lines changed: 27 additions & 4 deletions

File tree

src/components/src/main/java/org/apache/jmeter/timers/poissonarrivals/PreciseThroughputTimer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public long delay() {
9999
nextEvent = events.next();
100100
}
101101
long now = System.currentTimeMillis();
102-
long testStarted = JMeterContextService.getTestStartTime();
102+
long testStarted = JMeterContextService.getContext().getThreadGroup().getStartTime();
103103
long delay = (long) (nextEvent * TimeUnit.SECONDS.toMillis(1) + testStarted - now);
104104
if (log.isDebugEnabled()) {
105105
log.debug("Calculated delay is {}", delay);
@@ -117,7 +117,7 @@ public long delay() {
117117
}
118118

119119
private EventProducer getEventProducer() {
120-
long testStarted = JMeterContextService.getTestStartTime();
120+
long testStarted = JMeterContextService.getContext().getThreadGroup().getStartTime();
121121
long prevStarted = PREV_TEST_STARTED.get();
122122
if (prevStarted != testStarted && PREV_TEST_STARTED.compareAndSet(prevStarted, testStarted)) {
123123
// Reset counters if we are calculating throughput for a new test, see https://github.com/apache/jmeter/issues/6165

src/core/src/main/java/org/apache/jmeter/engine/StandardJMeterEngine.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ private void startThreadGroup(AbstractThreadGroup group, int groupCount, SearchB
574574
threadGroupTree.add(group, testLevelElements);
575575

576576
groups.add(group);
577+
group.setStartTime(System.currentTimeMillis());
577578
group.start(groupCount, notifier, threadGroupTree, this);
578579
} catch (JMeterStopTestException ex) { // NOSONAR Reported by log
579580
JMeterUtils.reportErrorToUser("Error occurred starting thread group :" + group.getName()+ ", error message:"+ex.getMessage()

src/core/src/main/java/org/apache/jmeter/threads/AbstractThreadGroup.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.time.Duration;
2222
import java.util.IdentityHashMap;
2323
import java.util.concurrent.atomic.AtomicInteger;
24+
import java.util.concurrent.atomic.AtomicLong;
2425

2526
import org.apache.jmeter.control.Controller;
2627
import org.apache.jmeter.control.IteratingController;
@@ -86,6 +87,8 @@ public abstract class AbstractThreadGroup extends AbstractTestElement
8687

8788
private final AtomicInteger numberOfThreads = new AtomicInteger(0); // Number of active threads in this group
8889

90+
private final AtomicLong startTime = new AtomicLong(0);
91+
8992
@Override
9093
public AbstractThreadGroupSchema getSchema() {
9194
return AbstractThreadGroupSchema.INSTANCE;
@@ -97,6 +100,23 @@ public AbstractThreadGroupSchema getSchema() {
97100
return new PropertiesAccessor<>(this, getSchema());
98101
}
99102

103+
/**
104+
* Get the time when this thread group has been started
105+
* @return time in milliseconds since epoch
106+
*/
107+
public long getStartTime() {
108+
return startTime.get();
109+
}
110+
111+
/**
112+
* Set the time when this thread group has been started.<br>
113+
* Will probably be set by StandardJMeterEngine.
114+
* @param startTime time in milliseconds since epoch
115+
*/
116+
public void setStartTime(long startTime) {
117+
this.startTime.set(startTime);
118+
}
119+
100120
/** {@inheritDoc} */
101121
@Override
102122
public boolean isDone() {

src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/OpenModelThreadGroup.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ public class OpenModelThreadGroup :
204204
val seed = randomSeed
205205
val rnd = if (seed == 0L) Random() else Random(seed)
206206
val gen = ThreadScheduleProcessGenerator(rnd, parsedSchedule)
207-
val testStartTime = System.currentTimeMillis()
207+
val testStartTime = this.startTime
208208
val executorService = Executors.newCachedThreadPool()
209209
this.executorService = executorService
210210
val starter = ThreadsStarter(testStartTime, executorService, activeThreads, gen) { threadNumber ->

xdocs/changes.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,16 @@ JMeter 6.x requires Java 17 or later for execution (Java 21 is recommended).
5757
Summary
5858
</p>
5959
<ul>
60-
<li><a href="#Bug fixes">Bug fixes</a></li>
60+
<li><a href="#Changes">Changes</a></li>
6161
</ul>
6262

6363
<ch_section>Changes</ch_section>
6464
<h3>General</h3>
6565
<ul>
6666
<li><pr>6220</pr> Require Java 17 or later for running JMeter</li>
6767
<li><pr>6274</pr> Change references to old MySQL driver to new class <code>com.mysql.cj.jdbc.Driver</code></li>
68+
<li><issue>6352</issue> Calculate delays in Open Model Thread Group and Precise Throughput
69+
Timer relative to start of Thread Group instead of the start of the test.</li>
6870
</ul>
6971

7072
<!-- =================== Thanks =================== -->

0 commit comments

Comments
 (0)