Skip to content

Instantly share code, notes, and snippets.

@jonatan-ivanov
Last active January 29, 2022 05:36
Show Gist options
  • Save jonatan-ivanov/0449619cb6f851ce67d70e47a6a1fb73 to your computer and use it in GitHub Desktop.
Save jonatan-ivanov/0449619cb6f851ce67d70e47a6a1fb73 to your computer and use it in GitHub Desktop.
CPU Metrics Demo
package org.example;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ThreadPoolExecutor;
import static java.util.concurrent.TimeUnit.SECONDS;
public class CpuMetricsDemo {
private static final int DURATION_SECONDS = 60;
public static void main(String[] args) throws InterruptedException {
generateLoad(4);
for (long i = 0; i < DURATION_SECONDS; i++) {
printInfo();
Thread.sleep(1_000);
}
System.exit(0);
}
private static void printInfo() {
Map<String, Object> info = new HashMap<>();
OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
com.sun.management.OperatingSystemMXBean sunOsMXBean = (com.sun.management.OperatingSystemMXBean) osMXBean; // com.ibm.lang.management.OperatingSystemMXBean for OpenJ9
System.out.println(Instant.now());
// AvailableProcessors is very useful in containerized environments where the processor count may not match to the number of processors of the host.
// The JVM uses this value to size:
// - GC threads (and also choosing the GC: 1 processor -> SerialGC)
// - JIT Compiler threads
// - Common Pool (ForkJoin API, CompletableFuture, .stream().parallel())
// see: https://docs.oracle.com/en/java/javase/17/gctuning/ergonomics.html
info.put("availableProcessors", Runtime.getRuntime().availableProcessors());
info.put("commonPool.parallelism", ForkJoinPool.commonPool().getParallelism());
// SystemLoadAverage shows you the average load for the last minute.
// This can be useful in containerized environments where the CPU resources might be limited so the avg load might be higher than the load you can see on the host.
// If you have 8 cores, and you put 4 of them under 100% load, the SystemLoadAverage should be around 4.0 (4 cores).
info.put("systemLoadAveragePerMinute", osMXBean.getSystemLoadAverage());
// ProcessCpuTime shows you how much time does the CPU spend for executing instructions of the JVM.
// The return value is in nanos, but it is not necessarily nanosecond-accurate.
// If you run your process for 10 seconds, and you put 1 core under 100% load, the processCpuTime will be 10 seconds.
// If you run your process for 60 seconds, and you put 4 cores under 100% load, the processCpuTime will be 240 (4*60) seconds.
info.put("processCpuTime", sunOsMXBean.getProcessCpuTime());
// SystemCpuLoad shows you "recent CPU usage" for the whole system.
// This can be useful in containerized environments where the CPU resources might be limited so the load might be higher than the load you can see on the host.
// The return value is a rate in the [0.0,1.0] interval:
// - 0.0 means that all CPUs were idle recently
// - 1.0 means that all CPUs were actively running 100% of the time recently
// - If you have 8 cores, and you put 4 cores under 100% load, systemCpuLoad will be around 0.5
info.put("systemCpuLoad", sunOsMXBean.getSystemCpuLoad());
// ProcessCpuLoad shows you "recent CPU usage" of the JVM.
// See systemCpuLoad for more details.
info.put("processCpuLoad", sunOsMXBean.getProcessCpuLoad());
info.forEach((key, value) -> System.out.println("\t" + key + ":" + value));
}
private static void generateLoad(int cpus) {
ExecutorService executor = new ThreadPoolExecutor(cpus, cpus, 0, SECONDS, new ArrayBlockingQueue<>(1));
Runtime.getRuntime().addShutdownHook(new Thread(executor::shutdownNow));
for (int i = 0; i < cpus; i++) {
executor.submit(CpuMetricsDemo::load);
}
}
private static void load() {
System.out.println(Thread.currentThread().getName() + " started");
for (;;) {
if (Thread.currentThread().isInterrupted()) {
break;
}
}
System.out.println(Thread.currentThread().getName() + " stopped");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment