All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.util.CallAnalyse Maven / Gradle / Ivy

There is a newer version: 3.1
Show newest version
/*
 * #%L
 * Nuiton Utils
 * %%
 * Copyright (C) 2004 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.util;

import org.apache.commons.collections.primitives.ArrayLongList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Cette classe permet de faire des analyses sur les appels de methode
 * En debut de methode on appelle la methode {@link #enter}, et en fin de methode
 * la methode {@link #exit}.
 * 

* Ensuite on peut récuperer les statistiques par Thread ou de tous les threads *

* On a comme statistique *

    *
  • le temps d'execution *
  • la memore utilisé *
  • le nombre d'appels *
* * @author Benjamin Poussin - [email protected] * @see TimeLog * Created: 25 aout 2005 14:09:22 CEST */ public class CallAnalyse { // CallAnalyse /** * Logger. */ private static final Log log = LogFactory.getLog(CallAnalyse.class); static private List listThreadStatistics = new ArrayList(); static private ThreadLocal stats = new ThreadLocal() { @Override protected synchronized ThreadStatistics initialValue() { ThreadStatistics result = new ThreadStatistics(); listThreadStatistics.add(result); return result; } }; /** * Permet d'activer les statistiques, pour le thread courant */ public static void activate() { stats.get().setActivated(true); } /** * Permet de desactiver les statistiques, pour le thread courant */ public static void desactivate() { stats.get().setActivated(false); } /** * Permet de savoir si les statistiques sont activées ou non, pour le * thread courant * @return FIXME */ public static boolean isActivate() { return stats.get().getActivated(); } /** * @param name le nom de l'appel a monitorer */ public static void enter(String name) { ThreadStatistics t = stats.get(); if (t.getActivated()) { t.get(name).enter(); } } /** * Indique la sortie de l'appel, name doit avoir ete utilisé lors d'un enter * * @param name le nom de l'appel a monitorer, doit etre identique a * celui utilisé pour la methode enter */ public static void exit(String name) { ThreadStatistics t = stats.get(); if (t.getActivated()) { t.get(name).exit(); } } /** * @return the statistics for the current thread */ public static ThreadStatistics getThreadStatistics() { return stats.get(); } /** * @return the statistics for all threads */ public static List getAllThreadStatistics() { return listThreadStatistics; } public static class ThreadStatistics extends TreeMap { /** */ private static final long serialVersionUID = -36051448464013504L; protected boolean activated = false; public boolean getActivated() { return activated; } public void setActivated(boolean activated) { this.activated = activated; } public CallStatistics get(String name) { CallStatistics result = super.get(name); if (result == null) { put(name, result = new CallStatistics(name)); } return result; } public String toString() { return values().toString(); } } /** * This method will get all the statistics from all the threads and put it * all together in a {@link Map} which key is the name of the watched * element and the value is its instance of {@link CallStatisticsSummary} * * @return A map with all collected statistics */ public static Map getSummary() { Map results = new HashMap(); for (ThreadStatistics stats : CallAnalyse.getAllThreadStatistics()) { for (String name : stats.keySet()) { CallStatisticsSummary stat = results.get(name); if (stat == null) { stat = new CallStatisticsSummary(name); results.put(name, stat); } stat.addCallStats(stats.get(name)); } } return results; } /** * CallStatistics is the class which handles values on excecution time and * memory usage. * Each CallStatistics object is for one particular name. * * @author bpoussin */ public static class CallStatistics implements Cloneable { protected String name = null; protected long calls = 0; protected long minTime = Long.MAX_VALUE; protected long maxTime = Long.MIN_VALUE; protected long sumTime = 0; protected long minMemory = Long.MAX_VALUE; protected long maxMemory = Long.MIN_VALUE; protected long sumMemory = 0; /** * pile contenant le temps de appel, util pour les appels recursifs */ protected ArrayLongList times = new ArrayLongList(); protected ArrayLongList memories = new ArrayLongList(); protected Runtime runtime = Runtime.getRuntime(); public CallStatistics(String name) { this.name = name; } public void enter() { times.add(System.nanoTime()); memories.add(getMemory()); } public void exit() { calls++; if (times.size() == 0) { log.info("To many exit call for " + name); return; } long time = times.removeElementAt(times.size() - 1); time = System.nanoTime() - time; if (time < minTime || minTime == Long.MAX_VALUE) { minTime = time; } if (time > maxTime) { maxTime = time; } sumTime += time; long memory = memories.removeElementAt(memories.size() - 1); memory = getMemory() - memory; if (memory < minMemory || minMemory == Long.MAX_VALUE) { minMemory = memory; } if (memory > maxMemory) { maxMemory = memory; } sumMemory += memory; } public String getName() { return name; } public long getCalls() { return calls; } public long getMinTime() { return minTime; } public long getMaxTime() { return maxTime; } public long getSumTime() { return sumTime; } public long getAvgTime() { if (calls == 0) { return 0; } else { return sumTime / calls; } } public long getMinMemory() { return minMemory; } public long getMaxMemory() { return maxMemory; } public long getSumMemory() { return sumMemory; } public long getAvgMemory() { if (calls == 0) { return 0; } else { return sumMemory / calls; } } protected long getMemory() { // runtime.gc(); return runtime.totalMemory() - runtime.freeMemory(); } @Override public String toString() { return getName() + " calls=" + getCalls() + " time=" + StringUtil.convertTime(getSumTime()) + "(" + StringUtil.convertTime(getMinTime()) + "/" + StringUtil.convertTime(getAvgTime()) + "/" + StringUtil.convertTime(getMaxTime()) + ")" + " memory=" + StringUtil.convertMemory(getSumMemory()) + "(" + StringUtil.convertMemory(getMinMemory()) + "/" + StringUtil.convertMemory(getAvgMemory()) + "/" + StringUtil.convertMemory(getMaxMemory()) + ")" ; } } //CallStatistics /** * This class is collecting data from different CallStatistics classes by * using the method {@link #addCallStats(org.nuiton.util.CallAnalyse.CallStatistics)}. * * @author thimel */ public static class CallStatisticsSummary extends CallStatistics { public CallStatisticsSummary(String name) { super(name); } /** * This methods read the given {@link CallStatistics} and add values to * its own * * @param other an other CallStatistics object */ public void addCallStats(CallStatistics other) { if (other == null || this.equals(other)) { return; } calls += other.getCalls(); if (other.getMinTime() < minTime || minTime == Long.MAX_VALUE) { minTime = other.getMinTime(); } if (other.getMaxTime() > maxTime) { maxTime = other.getMaxTime(); } sumTime += other.getSumTime(); if (other.getMinMemory() < minMemory || minMemory == Long.MAX_VALUE) { minMemory = other.getMinMemory(); } if (other.getMaxMemory() > maxMemory) { maxMemory = other.getMaxMemory(); } sumMemory += other.getSumMemory(); } } //CallStatisticsSummary } // CallAnalyse




© 2015 - 2024 Weber Informatics LLC | Privacy Policy