package ar.com.javacuriosities.concurrency.management; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; /* * En Java 1.5 se agregaron nuevas funcionalidades incluidas en el paquete java.lang.management. * * Se incluyeron distintos MXBean que ayudan a obtener información de los diferentes recursos. * * Platform resource Corresponding MXBean Number available * Compilation CompilationMXBean 0 or 1 * Garbage collection system GarbageCollectorMXBean At least 1 * Memory MemoryMXBean Exactly 1 Memory * managers MemoryManagerMXBean At least 1 * Threading ThreadMXBean Exactly 1 * Operating system OperatingSystemMXBean Exactly 1 * Runtime system RuntimeMXBean Exactly 1 * Class loading system ClassLoadingMXBean Exactly 1 * Memory resources MemoryPoolMXBean At least 1 * * * Introducción: * * Antes de Java 1.5 la única manera de hacer benchmark era usando lo que se conoce como "wall clock time" * * long startTime = System.currentTimeMillis(); * // Tareas * endTime = System.currentTimeMillis() - startTime; * * En Java 1.5 además del método currentTimeMillis() se agrega el método nanoTime(), que ofrece * el tiempo en nanosegundos * * long startTime = System.nanoTime(); * // Tareas * endTime = System.nanoTime() - startTime; * * Sin embargo estos dos métodos no son de mucha utilidad si nosotros queremos conocer estos * datos a nivel de Threads, por eso se incluyo ThreadMXBean el cual provee los siguientes datos * * "User time": Es el tiempo consumido por la aplicación en correr nuestro código. * "System time": Es el tiempo consumido por el SO en nombre de nuestra aplicación (Ejemplo I/O) * * "CPU time": Es la suma de User Time + System Time. Es el tiempo total usado por nuestra aplicación. * * Lo bueno es que podemos hacer cosas como lo siguiente * * ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); * long cpuTime = threadMXBean.getCurrentThreadCpuTime(); * * Con las líneas anteriores obtenemos el cpuTime para el hilo actual, obteniendo el startCpuTime y el * endCpuTime podemos ver cuanto tiempo es consumido por nuestro Thread */ public class Main { public static void main(String[] args) { // Creamos 4 threads los cuales imprimen el tiempo de CPU usado por cada uno Thread measure1 = new ThreadMeasure("Counter-1", 1000); Thread measure2 = new ThreadMeasure("Counter-2", 1000); Thread measure3 = new ThreadMeasure("Counter-3", 1000); Thread measure4 = new ThreadMeasure("Counter-4", 1000); // Iniciamos los 4 threads measure1.start(); measure2.start(); measure3.start(); measure4.start(); } private static final class ThreadMeasure extends Thread { // Variable que controla el maximo numero de ciclos private int maxCounter; public ThreadMeasure(String name, int maxCounter) { super(name); this.maxCounter = maxCounter; } /* * Sobrescribimos el método run() y como primer línea * pedimos el ThreadMXBean, luego pedimos el cpuTime y antes de terminar el * método run() volvemos a pedir el cpuTime para calcular la diferencia */ @Override public void run() { // Pedimos el ThreadMXBean ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); // Pedimos el cpuTime inicial long cpuTime = threadMXBean.getCurrentThreadCpuTime(); /* Creamos una variable la cual vamos a ir modificando en el ciclo * este código esta puesto porque si ponemos un ciclo vació el compilador * se da cuenta de esto y lo remueve para incrementar la performance */ long total = 0; for (int contador = 0; contador <= (maxCounter * maxCounter * maxCounter); contador++) { total += contador; total *= 10; } System.out.println(getName() + " -> " + total); // Calculamos la diferencia entre el final y el inicial cpuTime = threadMXBean.getCurrentThreadCpuTime() - cpuTime; // Imprimimos cuando tiempo consumió este hilo System.out.println("Thread: " + getName() + ": cpuTime = " + cpuTime); } } }