JVM Integration for Metrics - A set of classes which allow you to monitor critical aspects of your Java Virtual Machine using Metrics
—
CPU time measurement capabilities for performance monitoring and thread-specific timing analysis.
import com.codahale.metrics.jvm.CpuTimeClock;
import com.codahale.metrics.Clock;A specialized clock implementation that returns the current thread's CPU time for precise performance measurement.
/**
* A clock implementation which returns the current thread's CPU time.
*/
public class CpuTimeClock extends Clock {
/**
* Returns the current thread's CPU time in nanoseconds.
* @return CPU time tick for the current thread
*/
public long getTick();
}Usage Examples:
import com.codahale.metrics.*;
import com.codahale.metrics.jvm.CpuTimeClock;
// Create CPU time clock instance
CpuTimeClock cpuClock = new CpuTimeClock();
// Use with Timer for CPU time measurement
MetricRegistry registry = new MetricRegistry();
Timer cpuTimer = new Timer(registry.getMetricRegistry(), cpuClock);
registry.register("cpu-time-timer", cpuTimer);
// Measure CPU time for operations
Timer.Context context = cpuTimer.time();
try {
// Perform CPU-intensive operation
performComplexCalculation();
} finally {
context.stop(); // Records CPU time, not wall-clock time
}
// Direct CPU time measurement
long startCpuTime = cpuClock.getTick();
performOperation();
long endCpuTime = cpuClock.getTick();
long cpuTimeUsed = endCpuTime - startCpuTime;
System.out.println("CPU time used: " + cpuTimeUsed + " nanoseconds");
System.out.println("CPU time used: " + (cpuTimeUsed / 1_000_000.0) + " milliseconds");
// Compare with wall-clock time
Clock wallClock = Clock.defaultClock();
long startWall = wallClock.getTick();
long startCpu = cpuClock.getTick();
performOperationWithWaiting();
long endWall = wallClock.getTick();
long endCpu = cpuClock.getTick();
long wallTime = endWall - startWall;
long cpuTime = endCpu - startCpu;
System.out.println("Wall-clock time: " + (wallTime / 1_000_000.0) + " ms");
System.out.println("CPU time: " + (cpuTime / 1_000_000.0) + " ms");
System.out.println("CPU efficiency: " + ((double) cpuTime / wallTime * 100) + "%");Integration with Metrics Framework:
// Create histogram with CPU time measurement
Histogram cpuHistogram = new Histogram(new UniformReservoir()) {
private final CpuTimeClock cpuClock = new CpuTimeClock();
public void time(Runnable operation) {
long start = cpuClock.getTick();
try {
operation.run();
} finally {
long duration = cpuClock.getTick() - start;
update(duration);
}
}
};
// Usage
cpuHistogram.time(() -> {
// CPU-intensive operation
calculatePrimes(1000000);
});
// CPU time-based meter
Meter cpuMeter = new Meter(cpuClock);
registry.register("cpu-operations-rate", cpuMeter);
// Mark CPU-intensive operations
cpuMeter.mark(); // Records based on CPU time progressionPerformance Analysis Patterns:
public class CpuPerformanceAnalyzer {
private final CpuTimeClock cpuClock = new CpuTimeClock();
private final Clock wallClock = Clock.defaultClock();
public PerformanceMetrics analyzeOperation(Runnable operation) {
long startWall = wallClock.getTick();
long startCpu = cpuClock.getTick();
operation.run();
long endWall = wallClock.getTick();
long endCpu = cpuClock.getTick();
return new PerformanceMetrics(
endWall - startWall, // Wall time
endCpu - startCpu // CPU time
);
}
public static class PerformanceMetrics {
private final long wallTimeNanos;
private final long cpuTimeNanos;
public PerformanceMetrics(long wallTimeNanos, long cpuTimeNanos) {
this.wallTimeNanos = wallTimeNanos;
this.cpuTimeNanos = cpuTimeNanos;
}
public double getCpuEfficiency() {
return wallTimeNanos > 0 ? (double) cpuTimeNanos / wallTimeNanos : 0.0;
}
public long getWaitTimeNanos() {
return wallTimeNanos - cpuTimeNanos;
}
public boolean isCpuBound() {
return getCpuEfficiency() > 0.8; // More than 80% CPU usage
}
public boolean isIoBound() {
return getCpuEfficiency() < 0.2; // Less than 20% CPU usage
}
}
}
// Usage
CpuPerformanceAnalyzer analyzer = new CpuPerformanceAnalyzer();
PerformanceMetrics metrics = analyzer.analyzeOperation(() -> {
// Some operation to analyze
processData();
});
System.out.println("CPU efficiency: " + (metrics.getCpuEfficiency() * 100) + "%");
System.out.println("Wait time: " + (metrics.getWaitTimeNanos() / 1_000_000.0) + " ms");
System.out.println("Operation type: " +
(metrics.isCpuBound() ? "CPU-bound" :
metrics.isIoBound() ? "I/O-bound" : "Mixed"));Thread-Specific Behavior:
// CPU time is thread-specific
public class ThreadCpuMonitor {
public void demonstrateThreadSpecificity() {
CpuTimeClock cpuClock = new CpuTimeClock();
// Start background thread
Thread backgroundThread = new Thread(() -> {
long threadCpuStart = cpuClock.getTick();
// CPU-intensive work in background
burnCpu(1000);
long threadCpuEnd = cpuClock.getTick();
System.out.println("Background thread CPU time: " +
(threadCpuEnd - threadCpuStart) / 1_000_000.0 + " ms");
});
backgroundThread.start();
// Main thread CPU measurement (independent of background thread)
long mainCpuStart = cpuClock.getTick();
Thread.sleep(500); // This uses no CPU time
long mainCpuEnd = cpuClock.getTick();
System.out.println("Main thread CPU time during sleep: " +
(mainCpuEnd - mainCpuStart) / 1_000_000.0 + " ms"); // Should be near 0
try {
backgroundThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}Platform Considerations:
Monitoring Use Cases:
Install with Tessl CLI
npx tessl i tessl/maven-io-dropwizard-metrics--metrics-jvm