|
JMeter example source code file (ConstantThroughputTimer.java)
The JMeter ConstantThroughputTimer.java source code
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.timers;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.jmeter.engine.event.LoopIterationEvent;
import org.apache.jmeter.testbeans.TestBean;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestListener;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.AbstractThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
* This class implements a constant throughput timer. A Constant Throughtput
* Timer paces the samplers under its influence so that the total number of
* samples per unit of time approaches a given constant as much as possible.
*
* There are two different ways of pacing the requests:
* - delay each thread according to when it last ran
* - delay each thread according to when any thread last ran
*/
public class ConstantThroughputTimer extends AbstractTestElement implements Timer, TestListener, TestBean {
private static final long serialVersionUID = 3;
private static class ThroughputInfo{
final Object MUTEX = new Object();
long lastScheduledTime = 0;
}
private static final Logger log = LoggingManager.getLoggerForClass();
private static final double MILLISEC_PER_MIN = 60000.0;
/**
* Target time for the start of the next request. The delay provided by the
* timer will be calculated so that the next request happens at this time.
*/
private long previousTime = 0;
private String calcMode; // String representing the mode
// (Locale-specific)
private int modeInt; // mode as an integer
/**
* Desired throughput, in samples per minute.
*/
private double throughput;
//For calculating throughput across all threads
private final static ThroughputInfo allThreadsInfo = new ThroughputInfo();
//For holding the ThrougputInfo objects for all ThreadGroups. Keyed by AbstractThreadGroup objects
private final static Map<AbstractThreadGroup, ThroughputInfo> threadGroupsInfoMap =
new ConcurrentHashMap<AbstractThreadGroup, ThroughputInfo>();
/**
* Constructor for a non-configured ConstantThroughputTimer.
*/
public ConstantThroughputTimer() {
}
/**
* Sets the desired throughput.
*
* @param throughput
* Desired sampling rate, in samples per minute.
*/
public void setThroughput(double throughput) {
this.throughput = throughput;
}
/**
* Gets the configured desired throughput.
*
* @return the rate at which samples should occur, in samples per minute.
*/
public double getThroughput() {
return throughput;
}
public String getCalcMode() {
return calcMode;
}
// Needed by test code
int getCalcModeInt() {
return modeInt;
}
public void setCalcMode(String mode) {
this.calcMode = mode;
// TODO find better way to get modeInt
this.modeInt = ConstantThroughputTimerBeanInfo.getCalcModeAsInt(calcMode);
}
/**
* Retrieve the delay to use during test execution.
*
* @see org.apache.jmeter.timers.Timer#delay()
*/
public long delay() {
long currentTime = System.currentTimeMillis();
/*
* If previous time is zero, then target will be in the past.
* This is what we want, so first sample is run without a delay.
*/
long currentTarget = previousTime + calculateDelay();
if (currentTime > currentTarget) {
// We're behind schedule -- try to catch up:
previousTime = currentTime;
return 0;
}
previousTime = currentTarget;
return currentTarget - currentTime;
}
/**
* @param currentTime
* @return new Target time
*/
// TODO - is this used? (apart from test code)
protected long calculateCurrentTarget(long currentTime) {
return currentTime + calculateDelay();
}
// Calculate the delay based on the mode
private long calculateDelay() {
long delay = 0;
// N.B. we fetch the throughput each time, as it may vary during a test
double msPerRequest = (MILLISEC_PER_MIN / getThroughput());
switch (modeInt) {
case 1: // Total number of threads
delay = (long) (JMeterContextService.getNumberOfThreads() * msPerRequest);
break;
case 2: // Active threads in this group
delay = (long) (JMeterContextService.getContext().getThreadGroup().getNumberOfThreads() * msPerRequest);
break;
case 3: // All threads - alternate calculation
delay = calculateSharedDelay(allThreadsInfo,(long) msPerRequest);
break;
case 4: //All threads in this group - alternate calculation
final org.apache.jmeter.threads.AbstractThreadGroup group =
JMeterContextService.getContext().getThreadGroup();
ThroughputInfo groupInfo;
synchronized (threadGroupsInfoMap) {
groupInfo = threadGroupsInfoMap.get(group);
if (groupInfo == null) {
groupInfo = new ThroughputInfo();
threadGroupsInfoMap.put(group, groupInfo);
}
}
delay = calculateSharedDelay(groupInfo,(long) msPerRequest);
break;
default: // e.g. 0
delay = (long) msPerRequest; // i.e. * 1
break;
}
return delay;
}
private long calculateSharedDelay(ThroughputInfo info, long milliSecPerRequest) {
final long now = System.currentTimeMillis();
final long calculatedDelay;
//Synchronize on the info object's MUTEX to ensure
//Multiple threads don't update the scheduled time simultaneously
synchronized (info.MUTEX) {
final long nextRequstTime = info.lastScheduledTime + milliSecPerRequest;
info.lastScheduledTime = Math.max(now, nextRequstTime);
calculatedDelay = info.lastScheduledTime - now;
}
return Math.max(calculatedDelay, 0);
}
private synchronized void reset() {
allThreadsInfo.lastScheduledTime = 0;
threadGroupsInfoMap.clear();
previousTime = 0;
}
/**
* Provide a description of this timer class.
*
* TODO: Is this ever used? I can't remember where. Remove if it isn't --
* TODO: or obtain text from bean's displayName or shortDescription.
*
* @return the description of this timer class.
*/
@Override
public String toString() {
return JMeterUtils.getResString("constant_throughput_timer_memo"); //$NON-NLS-1$
}
/**
* Get the timer ready to compute delays for a new test.
* <p>
* {@inheritDoc}
*/
public void testStarted()
{
log.debug("Test started - reset throughput calculation.");
reset();
}
/**
* {@inheritDoc}
*/
public void testEnded() {
}
/**
* {@inheritDoc}
*/
public void testStarted(String host) {
testStarted();
}
/**
* {@inheritDoc}
*/
public void testEnded(String host) {
}
/**
* {@inheritDoc}
*/
public void testIterationStart(LoopIterationEvent event) {
}
}
Other JMeter examples (source code examples)Here is a short list of links related to this JMeter ConstantThroughputTimer.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.