/*
* Copyright 2012 The Netty Project
*
* The Netty Project 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 io.netty.test.udt.util;
import com.google.caliper.Measurement;
import com.google.caliper.MeasurementSet;
import com.google.caliper.Run;
import com.google.caliper.Scenario;
import com.google.caliper.ScenarioResult;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Meter;
import com.yammer.metrics.core.MetricsRegistry;
import com.yammer.metrics.core.Timer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Caliper measure with Metrics provider.
* <p>
* measure up to 3 values: {@link #rate()}, {@link #time()}, {@link #size()}
*/
public class CaliperMeasure {
/**
* Gauge any double value
*/
public static class SizeGuage extends Gauge<Double> {
private volatile Double size = 0.0;
@Override
public Double value() {
return size;
}
public void value(final double size) {
this.size = size;
}
}
/**
* Default rate measurement units.
*/
private static final Map<String, Integer> RATE_UNIT = new HashMap<String, Integer>();
static {
RATE_UNIT.put("Rate B/s", 1);
RATE_UNIT.put("Rate KB/s", 1024);
RATE_UNIT.put("Rate MB/s", 1024 * 1024);
RATE_UNIT.put("Rate GB/s", 1024 * 1024 * 1024);
}
/**
* Default time measurement units.
*/
private static final Map<String, Integer> TIME_UNIT = new HashMap<String, Integer>();
static {
TIME_UNIT.put("Time ns", 1);
TIME_UNIT.put("Time us", 1000);
TIME_UNIT.put("Time ms", 1000 * 1000);
TIME_UNIT.put("Time s ", 1000 * 1000 * 1000);
}
/**
* Default size measurement units.
*/
private static final Map<String, Integer> SIZE_UNIT = new HashMap<String, Integer>();
static {
SIZE_UNIT.put("Size B", 1);
SIZE_UNIT.put("Size KB", 1024);
SIZE_UNIT.put("Size MB", 1024 * 1024);
SIZE_UNIT.put("Size GB", 1024 * 1024 * 1024);
}
private final Map<Long, Measurement> rateMap = new HashMap<Long, Measurement>();
private final Map<Long, Measurement> timeMap = new HashMap<Long, Measurement>();
private final Map<Long, Measurement> sizeMap = new HashMap<Long, Measurement>();
private final MetricsRegistry metrics = new MetricsRegistry();
private final Meter rate = metrics.newMeter(getClass(), "rate", "bytes",
TimeUnit.SECONDS);
private final Timer time = metrics.newTimer(getClass(), "time",
TimeUnit.NANOSECONDS, TimeUnit.SECONDS);
private final SizeGuage size = new SizeGuage();
{
metrics.newGauge(getClass(), "", size);
}
/**
* Rate meter.
*/
public Meter rate() {
return rate;
}
/**
* Time meter.
*/
public Timer time() {
return time;
}
/**
* Size meter.
*/
public SizeGuage size() {
return size;
}
/**
* Workaround: zero breaks gwt web app.
*/
private static double filter(final double value) {
if (value <= 0.0) {
return 1.0;
} else {
return value;
}
}
/**
* Perform measurement; convert from metrics into caliper.
*/
@SuppressWarnings("FloatingPointEquality")
public void mark() {
final double rateValue = filter(rate.oneMinuteRate());
final double timeValue = filter(time.mean());
final double sizeValue = filter(size.value());
if (rateValue == 1.0 && timeValue == 1.0 && sizeValue == 1.0) {
/** ignore complete blank entries */
return;
}
final Measurement markRate = new Measurement(RATE_UNIT, rateValue,
rateValue);
rateMap.put(System.nanoTime(), markRate);
final Measurement markTime = new Measurement(TIME_UNIT, timeValue,
timeValue);
timeMap.put(System.nanoTime(), markTime);
final Measurement markSize = new Measurement(SIZE_UNIT, sizeValue,
sizeValue);
sizeMap.put(System.nanoTime(), markSize);
}
private final Map<String, String> variables = new HashMap<String, String>();
/**
* Caliper scenario variables.
*/
public Map<String, String> variables() {
return variables;
}
private static MeasurementSet measurementSet(final Map<Long, Measurement> map) {
final Measurement[] array = map.values().toArray(new Measurement[map.size()]);
return new MeasurementSet(array);
}
/**
* Attach this measure to parent caliper run.
*/
public void appendTo(final Run run) {
final Scenario scenario = new Scenario(variables());
/** display rate as caliper durations */
final MeasurementSet timeSet = measurementSet(rateMap);
final String timeLog = null;
/** display time as caliper instances */
final MeasurementSet instSet = measurementSet(timeMap);
final String instLog = null;
/** display size as caliper memory */
final MeasurementSet heapSet = measurementSet(sizeMap);
final String heapLog = null;
final ScenarioResult scenarioResult = new ScenarioResult(timeSet,
timeLog, instSet, instLog, heapSet, heapLog);
final Map<Scenario, ScenarioResult> measurements = run
.getMeasurements();
measurements.put(scenario, scenarioResult);
}
/**
* Terminate metrics resources.
*/
public void shutdown() {
rate.stop();
time.stop();
metrics.shutdown();
}
}