blob: 6be71c84db7b677ad78130c62f834287fcae780f [file] [log] [blame]
package org.apache.cassandra.stress.util;
/*
*
* 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.
*
*/
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
// represents measurements taken over an interval of time
// used for both single timer results and merged timer results
public final class TimingInterval
{
// nanos
private final long start;
private final long end;
public final long maxLatency;
public final long pauseLength;
public final long pauseStart;
public final long totalLatency;
// discrete
public final long partitionCount;
public final long rowCount;
public final long operationCount;
public final long errorCount;
final SampleOfLongs sample;
public String toString()
{
return String.format("Start: %d end: %d maxLatency: %d pauseLength: %d pauseStart: %d totalLatency: %d" +
" pCount: %d rcount: %d opCount: %d errors: %d", start, end, maxLatency, pauseLength,
pauseStart, totalLatency, partitionCount, rowCount, operationCount, errorCount);
}
TimingInterval(long time)
{
start = end = time;
maxLatency = totalLatency = 0;
partitionCount = rowCount = operationCount = errorCount = 0;
pauseStart = pauseLength = 0;
sample = new SampleOfLongs(new long[0], 1d);
}
TimingInterval(long start, long end, long maxLatency, long pauseStart, long pauseLength, long partitionCount,
long rowCount, long totalLatency, long operationCount, long errorCount, SampleOfLongs sample)
{
this.start = start;
this.end = Math.max(end, start);
this.maxLatency = maxLatency;
this.partitionCount = partitionCount;
this.rowCount = rowCount;
this.totalLatency = totalLatency;
this.errorCount = errorCount;
this.operationCount = operationCount;
this.pauseStart = pauseStart;
this.pauseLength = pauseLength;
this.sample = sample;
}
// merge multiple timer intervals together
static TimingInterval merge(Iterable<TimingInterval> intervals, int maxSamples, long start)
{
ThreadLocalRandom rnd = ThreadLocalRandom.current();
long operationCount = 0, partitionCount = 0, rowCount = 0, errorCount = 0;
long maxLatency = 0, totalLatency = 0;
List<SampleOfLongs> latencies = new ArrayList<>();
long end = 0;
long pauseStart = 0, pauseEnd = Long.MAX_VALUE;
for (TimingInterval interval : intervals)
{
if (interval != null)
{
end = Math.max(end, interval.end);
operationCount += interval.operationCount;
maxLatency = Math.max(interval.maxLatency, maxLatency);
totalLatency += interval.totalLatency;
partitionCount += interval.partitionCount;
rowCount += interval.rowCount;
errorCount += interval.errorCount;
latencies.addAll(Arrays.asList(interval.sample));
if (interval.pauseLength > 0)
{
pauseStart = Math.max(pauseStart, interval.pauseStart);
pauseEnd = Math.min(pauseEnd, interval.pauseStart + interval.pauseLength);
}
}
}
if (pauseEnd < pauseStart || pauseStart <= 0)
{
pauseEnd = pauseStart = 0;
}
return new TimingInterval(start, end, maxLatency, pauseStart, pauseEnd - pauseStart, partitionCount, rowCount,
totalLatency, operationCount, errorCount, SampleOfLongs.merge(rnd, latencies, maxSamples));
}
public double opRate()
{
return operationCount / ((end - start) * 0.000000001d);
}
public double adjustedRowRate()
{
return rowCount / ((end - (start + pauseLength)) * 0.000000001d);
}
public double partitionRate()
{
return partitionCount / ((end - start) * 0.000000001d);
}
public double rowRate()
{
return rowCount / ((end - start) * 0.000000001d);
}
public double meanLatency()
{
return (totalLatency / (double) operationCount) * 0.000001d;
}
public double maxLatency()
{
return maxLatency * 0.000001d;
}
public double medianLatency()
{
return sample.medianLatency();
}
// 0 < rank < 1
public double rankLatency(float rank)
{
return sample.rankLatency(rank);
}
public long runTime()
{
return (end - start) / 1000000;
}
public final long endNanos()
{
return end;
}
public long startNanos()
{
return start;
}
public static enum TimingParameter
{
OPRATE, ROWRATE, ADJROWRATE, PARTITIONRATE, MEANLATENCY, MAXLATENCY, MEDIANLATENCY, RANKLATENCY,
ERRORCOUNT, PARTITIONCOUNT
}
String getStringValue(TimingParameter value)
{
return getStringValue(value, Float.NaN);
}
String getStringValue(TimingParameter value, float rank)
{
switch (value)
{
case OPRATE: return String.format("%.0f", opRate());
case ROWRATE: return String.format("%.0f", rowRate());
case ADJROWRATE: return String.format("%.0f", adjustedRowRate());
case PARTITIONRATE: return String.format("%.0f", partitionRate());
case MEANLATENCY: return String.format("%.1f", meanLatency());
case MAXLATENCY: return String.format("%.1f", maxLatency());
case MEDIANLATENCY: return String.format("%.1f", medianLatency());
case RANKLATENCY: return String.format("%.1f", rankLatency(rank));
case ERRORCOUNT: return String.format("%d", errorCount);
case PARTITIONCOUNT: return String.format("%d", partitionCount);
default: throw new IllegalStateException();
}
}
}