org.codehaus.mojo.chronos.responsetime.ResponsetimeSamples.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.chronos.responsetime.ResponsetimeSamples.java

Source

/*
 * Chronos - Copyright (C) 2011 National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
 *
 * All source code and information supplied as part of Chronos is
 * copyright to National Board of e-Health.
 *
 * The source code has been released under a dual license - meaning you can
 * use either licensed version of the library with your code.
 *
 * It is released under the LGPL (GNU Lesser General Public License), either
 * version 2.1 of the License, or (at your option) any later version. A copy
 * of which can be found at the link below.
 * http://www.gnu.org/copyleft/lesser.html
 *
 * $HeadURL$
 * $Id$
 */
package org.codehaus.mojo.chronos.responsetime;

import org.apache.commons.math.stat.StatUtils;
import org.codehaus.mojo.chronos.Utils;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.MovingAverage;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesDataItem;

import java.io.Serializable;
import java.util.*;

/**
 * Contains info from a jmeter jtl file.
 * 
 * @author ksr@lakeside.dk
 */
public abstract class ResponsetimeSamples implements Serializable {

    private static final int PERCENTILE = 95;

    private static final long serialVersionUID = 4056724466498233661L;

    /** <code>List</code> containing loaded samples */
    protected final List samples = new ArrayList();

    /** <code>int</code> representing the number of succeeded samples */
    protected int succeeded;

    public final void addAll(ResponsetimeSamples other) {
        Iterator it = other.samples.iterator();
        while (it.hasNext()) {
            ResponsetimeSample sample = (ResponsetimeSample) it.next();
            add(sample);
        }
    }

    /**
     * add a (hopefully successful) sample.
     * 
     * @param sample
     *            a JMeterSample
     */
    public final void add(ResponsetimeSample sample) {
        samples.add(sample);
        if (sample.isSuccess()) {
            succeeded++;
        }
    }

    /**
     * @return the number of samples
     */
    public final int size() {
        return samples.size();
    }

    /**
     * @return the successrate (in percentage)
     */
    public final double getSuccessrate() {
        return 100 * ((double) getSucceeded()) / samples.size();
    }

    /**
     * @return the number of failed samples
     */
    public final int getFailed() {
        return samples.size() - getSucceeded();
    }

    /**
     * @return the number of succeeded samples
     */
    public final int getSucceeded() {
        return succeeded;
    }

    /**
     * @param responsetimedivider
     *            TODO
     * @return the average responsetime of all samples
     */
    public final double getAverage(int responsetimedivider) {
        return StatUtils.mean(extractResponsetimes(responsetimedivider));
    }

    /**
     * @param responsetimedivider
     *            TODO
     * @return the minimum responsetime of all samples
     */
    public final double getMin(int responsetimedivider) {
        return StatUtils.min(extractResponsetimes(responsetimedivider));
    }

    /**
     * @param responsetimedivider
     *            TODO
     * @return the maximum responsetime of all samples
     */
    public final double getMax(int responsetimedivider) {
        return StatUtils.max(extractResponsetimes(responsetimedivider));
    }

    /**
     * @param responsetimedivider
     *            TODO
     * @return the 95% fractile of all responsetimes
     */
    public final double getPercentile95(int responsetimedivider) {
        return StatUtils.percentile(extractResponsetimes(responsetimedivider), PERCENTILE);
    };

    /**
     * Note that the samples is ordered by timestamp, so the first one has the lowest timestamp.
     * 
     * @return the first timestamp of all samples
     */
    public final long getFirstTimestamp() {
        ResponsetimeSample responsetimeSample = (ResponsetimeSample) samples.get(0);
        return responsetimeSample.getTimestamp();
    }

    /**
     * Extracts all responsetimes.
     * 
     * @param responsetimedivider
     * @return the responsetimes as an array
     */
    public final double[] extractResponsetimes(int responsetimedivider) {
        double[] responsetimes = new double[samples.size()];
        int i = 0;
        for (Iterator it = samples.iterator(); it.hasNext();) {
            ResponsetimeSample sample = (ResponsetimeSample) it.next();
            responsetimes[i++] = sample.getResponsetime() / responsetimedivider;
        }
        return responsetimes;
    }

    public final void appendResponsetimes(TimeSeries series, int responsetimeDivider) {
        long delta = getFirstTimestamp();
        for (Iterator it = samples.iterator(); it.hasNext();) {
            ResponsetimeSample sample = (ResponsetimeSample) it.next();
            Millisecond timestamp = Utils.createMS(sample.getTimestamp() - delta);
            double responseTime = sample.getResponsetime() / responsetimeDivider;
            series.addOrUpdate(timestamp, responseTime);
        }
    }

    public final void appendThreadCounts(TimeSeries series, long threadCountDuration) {
        if (samples.size() > 0) {
            long firstSerial = getFirstTimestamp();
            Map activeThreads = new HashMap();
            for (Iterator it = samples.iterator(); it.hasNext();) {
                ResponsetimeSample sample = (ResponsetimeSample) it.next();
                int threadCount = activeThreads.size();
                for (Iterator it2 = activeThreads.keySet().iterator(); it2.hasNext();) {
                    String key = (String) it2.next();
                    if (sample.getTimestamp() > ((ResponsetimeSample) activeThreads.get(key)).getTimestamp()
                            + threadCountDuration) {
                        it2.remove();
                    }
                }
                activeThreads.put(sample.getThreadId(), sample);

                if (threadCount != activeThreads.size()) {
                    series.addOrUpdate(Utils.createMS(sample.getTimestamp() - firstSerial), threadCount);
                    series.addOrUpdate(Utils.createMS(sample.getTimestamp() - firstSerial + 1),
                            activeThreads.size());
                }
            }
            ResponsetimeSample sample = (ResponsetimeSample) samples.get(samples.size() - 1);
            series.addOrUpdate(Utils.createMS(sample.getTimestamp() - firstSerial + 1), activeThreads.size());
        }
    }

    public final TimeSeries createMovingThroughput(String name, final int responsetimedivider) {
        TimeSeries series = new TimeSeries(name, Millisecond.class);
        if (samples.isEmpty()) {
            return series;
        }

        Collections.sort(samples, new Comparator() {
            public int compare(Object arg1, Object arg2) {
                ResponsetimeSample sample1 = (ResponsetimeSample) arg1;
                ResponsetimeSample sample2 = (ResponsetimeSample) arg2;
                long endtime1 = sample1.getTimestamp() + (long) sample1.getResponsetime() / responsetimedivider;
                long endtime2 = sample2.getTimestamp() + (long) sample2.getResponsetime() / responsetimedivider;
                return (int) (endtime1 - endtime2);
            }
        });

        int periodLength = 1000;
        long rampUpTime = 0;
        int measurements = 0;
        final long firstAllowedTimestamp = getFirstTimestamp() + rampUpTime;
        long periodStart = firstAllowedTimestamp;
        long periodEnd = periodStart + periodLength;
        for (int i = 0; i < samples.size(); i++) {
            ResponsetimeSample sample = (ResponsetimeSample) samples.get(i);
            long sampleEndTime = sample.getTimestamp() + sample.getResponsetime() / responsetimedivider;
            if (sampleEndTime < periodStart) {
                continue;
            }
            if (sampleEndTime <= periodEnd) {
                measurements++;
            } else {
                if (measurements > 0) {
                    series.addOrUpdate(Utils.createMS(periodEnd - firstAllowedTimestamp),
                            measurements * responsetimedivider);
                } else {
                    series.addOrUpdate(Utils.createMS(periodEnd - firstAllowedTimestamp), null);
                }
                measurements = 1;
                periodStart = periodEnd;
                periodEnd = periodStart + periodLength;
            }
        }
        return series;
    }

    /**
     * 
     * @param responsetimedivider
     *            TODO
     * @return the maximum of a moving average of the throughput
     */
    public final double getMaxAverageThroughput(int averageduration, int responsetimedivider) {
        TimeSeries series = createMovingThroughput("", responsetimedivider);
        TimeSeries averageseries = MovingAverage.createMovingAverage(series, "", averageduration, 0);
        double max = 0;
        for (Iterator it = averageseries.getItems().iterator(); it.hasNext();) {
            TimeSeriesDataItem item = (TimeSeriesDataItem) it.next();
            if (item.getValue() != null) {
                max = Math.max(max, item.getValue().doubleValue());
            }
        }
        return max;
    }

    public final long getTotalTime() {
        ResponsetimeSample first = (ResponsetimeSample) samples.get(0);
        ResponsetimeSample last = (ResponsetimeSample) samples.get(samples.size() - 1);
        return last.getTimestamp() + last.getResponsetime() - first.getTimestamp();
    }
}