blob: aff23e27065b2a9e9201c9e3ae0591274c94e937 [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.utilint;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
/**
* Maintain interval and cumulative stats for a given set of operations, as
* well as a activityCounter that generates thread dumps if operations take too
* long. The markStart and markFinish methods can be used to bracket each
* tracked operation.
*/
public class StatsTracker<T> {
/* Latency stats. */
private final Map<T, LatencyStat> intervalLatencies;
private final Map<T, LatencyStat> cumulativeLatencies;
/*
* ActivityCounter tracks throughput and dumps thread stacktraces when
* throughput drops.
*/
private final ActivityCounter activityCounter;
/**
* The logger is used for activity stack traces.
*/
public StatsTracker(T[] opTypes,
Logger stackTraceLogger,
int activeThreadThreshold,
long threadDumpIntervalMillis,
int threadDumpMax,
int maxTrackedLatencyMillis) {
this.intervalLatencies = new HashMap<T, LatencyStat>();
this.cumulativeLatencies = new HashMap<T, LatencyStat>();
for (T opType : opTypes) {
intervalLatencies.put
(opType, new LatencyStat(maxTrackedLatencyMillis));
cumulativeLatencies.put
(opType, new LatencyStat(maxTrackedLatencyMillis));
}
activityCounter = new ActivityCounter(activeThreadThreshold,
threadDumpIntervalMillis,
threadDumpMax,
stackTraceLogger);
}
/**
* Track the start of a operation.
* @return the value of System.nanoTime, for passing to markFinish.
*/
public long markStart() {
activityCounter.start();
return System.nanoTime();
}
/**
* Track the end of an operation.
* @param startTime should be the value returned by the corresponding call
* to markStart
*/
public void markFinish(T opType, long startTime) {
markFinish(opType, startTime, 1);
}
/**
* Track the end of an operation.
* @param startTime should be the value returned by the corresponding call
* to markStart
*/
public void markFinish(T opType, long startTime, int numOperations) {
try {
if (numOperations == 0) {
return;
}
if (opType != null) {
long elapsed = System.nanoTime() - startTime;
intervalLatencies.get(opType).set(numOperations, elapsed);
cumulativeLatencies.get(opType).set(numOperations, elapsed);
}
} finally {
/* Must be invoked to clear the ActivityCounter stats. */
activityCounter.finish();
}
}
/**
* Should be called after each interval latency stat collection, to reset
* for the next period's collection.
*/
public void clearLatency() {
for (Map.Entry<T, LatencyStat> e : intervalLatencies.entrySet()) {
e.getValue().clear();
}
}
public Map<T, LatencyStat> getIntervalLatency() {
return intervalLatencies;
}
public Map<T, LatencyStat> getCumulativeLatency() {
return cumulativeLatencies;
}
/**
* For unit test support.
*/
public int getNumCompletedDumps() {
return activityCounter.getNumCompletedDumps();
}
}