All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.blazemeter.jmeter.threads.arrivals.ArrivalsThreadStarter Maven / Gradle / Ivy

package com.blazemeter.jmeter.threads.arrivals;

import com.blazemeter.jmeter.threads.AbstractThreadStarter;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.threads.ListenerNotifier;
import org.apache.jorphan.collections.ListedHashTree;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

public class ArrivalsThreadStarter extends AbstractThreadStarter {
    private static final Logger log = LoggingManager.getLoggerForClass();
    private ArrivalsThreadGroup arrivalsTG;
    protected long scheduledCount = 0;
    protected double rollingTime = 0;

    public ArrivalsThreadStarter(int groupIndex, ListenerNotifier listenerNotifier, ListedHashTree listedHashTree, StandardJMeterEngine standardJMeterEngine, ArrivalsThreadGroup owner) {
        super(groupIndex, owner, listedHashTree, listenerNotifier, standardJMeterEngine);
        arrivalsTG = owner;
    }

    protected void supplyActiveThreads() throws InterruptedException {
        while (needMoreArrivals()) {
            if (!arrivalsTG.releasedPoolThread()) {
                if (arrivalsTG.canCreateMoreThreads()) {
                    addActiveThread();
                } else {
                    log.debug("Not creating thread because of concurrency limit");
                }
            }
        }
    }

    public synchronized boolean needMoreArrivals() throws InterruptedException {
        if (rollingTime > 0) { // a case for very first thread
            while (rollingTime >= System.currentTimeMillis()) {
                long maxWait = (long) (rollingTime - System.currentTimeMillis());
                if (maxWait > 0) {
                    log.debug("Waiting " + maxWait);
                    wait(maxWait);
                }
            }
        } else {
            rollingTime = System.currentTimeMillis();
            startTime = rollingTime / 1000.0;
        }

        double currentRate;
        do {
            currentRate = getCurrentRate();
            if (currentRate == 0) {
                log.debug("Zero arrivals rate, waiting a bit");
                rollingTime += 200; // FIXME: magic constant
                Thread.sleep(200);
            }
        } while (currentRate == 0);

        if (currentRate < 0) {
            log.info("Duration limit reached, no more arrivals needed, had arrivals: " + scheduledCount);
            ((ArrivalsThreadGroup) owner).setArrivalsLimit(String.valueOf(scheduledCount));
            return false;
        }
        tickRollingTime(currentRate);
        return !owner.isLimitReached();
    }


    // ported from Taurus PBench module
    protected double getCurrentRate() {
        long rampUp = owner.getRampUpSeconds();
        long hold = owner.getHoldSeconds();
        long steps = owner.getStepsAsLong();
        double throughput = owner.getTargetLevelFactored();
        double timeOffset = rollingTime / 1000.0 - startTime;

        if (timeOffset >= rampUp + hold) {
            return -1; // means no more requests
        }

        if (rampUp == 0 || timeOffset > rampUp) {
            return throughput;
        } else if (steps > 0) {
            double stepSize = throughput / (double) steps;
            double stepLen = rampUp / (double) steps;
            return stepSize * (Math.floor(timeOffset / stepLen) + 1);
        } else {
            double slope = throughput / rampUp;
            return slope * Math.sqrt(2 * scheduledCount / slope);
        }
    }

    protected void tickRollingTime(double currentRate) {
        if (currentRate > 0) {
            double delay = currentRate > 0 ? (1000.0 / currentRate) : 0;
            rollingTime += delay;
            scheduledCount++;
        } else {
            log.debug("Negative arrivals rate, ignoring");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy