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

com.venky.core.log.TimerStatistics Maven / Gradle / Ivy

There is a newer version: 1.18
Show newest version
package com.venky.core.log;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedSet;
import java.util.Stack;
import java.util.TreeSet;

import com.venky.core.string.StringUtil;
import com.venky.core.util.Bucket;


public class TimerStatistics {
	private final String context;
	private final Bucket callCount ;
	private final Bucket elapsedTime; 
	private TimerStatistics(String context){
		this.context = context;
		this.callCount = new Bucket();
		this.elapsedTime = new Bucket();
	}
	
	private static ThreadLocal> timerStatisticsInThread = new ThreadLocal>();
	static Map getTimerStatistics(){
		Map timerStatistics =  timerStatisticsInThread.get();
		if (timerStatistics == null){
			timerStatistics = new HashMap();
			timerStatisticsInThread.set(timerStatistics);
		}
		return timerStatistics;
	}
	
	private static ThreadLocal> timerStackInThread = new ThreadLocal>();
	static Stack getTimerStack(){
		Stack timerStack = timerStackInThread.get();
		if (timerStack == null){
			timerStack = new Stack();
			timerStackInThread.set(timerStack);
		}
		return timerStack;
	}
	
	private static ThreadLocal enabled = new ThreadLocal(); 
	public static void setEnabled(boolean value){
		enabled.set(value);
	}
	public static boolean isEnabled(){
		Boolean b = enabled.get();
		if (b == null){
			return false;
		}
		return b.booleanValue();
	}
	
	public static class Timer {
		public static Timer startTimer(){
			return startTimer(null);
		}
		public static Timer startTimer(String ctx){
			return startTimer(ctx,false);
		}
		
		public static Timer startTimer(String ctx,boolean additive){
			if (!isEnabled()){
				return dummy;
			}
			String context = getCaller() + (ctx == null ? "" : ":"+ StringUtil.valueOf(ctx));
			Map timerStatistics = getTimerStatistics();
			
			TimerStatistics ts = timerStatistics.get(context);
			if (ts == null){
				ts = new TimerStatistics(context);
				timerStatistics.put(context, ts);
			}
			Timer timer = new Timer(context,additive);
			timer.start();
			return timer;
		}

		private static StackTraceElement getCaller(){
			StackTraceElement[] elements = new Exception().getStackTrace();
			for (StackTraceElement element: elements){
				if (!element.getClassName().equals(Timer.class.getName())){
					return element;
				}
			}
			throw new RuntimeException("Timer class cannot be timed!");
		}
		
		private static final Timer dummy = new Timer("dummy");
		
		private final String key; 
		private final boolean additive;
		public Timer(String key){
			this(key,false);
		}
		public Timer(String key,boolean additive){
			this.key = key;
			this.additive = additive;
		}
		
		private Long start = null;
		private void start(){
			if (!isEnabled()){
				return ;
			}
			Stack timerStack = getTimerStack();
			if (!timerStack.isEmpty()){
				Timer previous = timerStack.peek();
				if (!previous.additive){
					previous.suspend();
				}
			}
			timerStack.push(this);
			start = System.currentTimeMillis();
		}
		
		public void stop(){
			if (!isEnabled()){
				return ;
			}
			TimerStatistics statistics = suspend();
			statistics.callCount.increment();
			Stack timerStack = getTimerStack();
			Timer last  = null;

			//Pop timer stack till this.
			while(last != this && !timerStack.isEmpty()){
				last = timerStack.pop();
			}

			if (!timerStack.isEmpty()){
				Timer previous = timerStack.peek();
				if (!previous.additive){
					previous.start();
				}
			}
		}
		private TimerStatistics suspend(){
			if (!isEnabled()){
				return null;
			}
			long now = System.currentTimeMillis();
			TimerStatistics statistics = getTimerStatistics().get(key);
			if (start != null){
				statistics.elapsedTime.increment(now - start);
				start = null;
			}
			return statistics;
		}
	}
	
	
	public String getStatistics(){
		if (!isEnabled()){
			return "";
		}
		StringBuilder b = new StringBuilder();
		if (callCount.intValue() > 0){
			b.append(context).append("|").append(callCount.intValue()).append("|").append(elapsedTime.value()).append("|").append(elapsedTime.value()/callCount.intValue());
		}
		return b.toString();
	}
	
	
	public static void dumpStatistics(){
		if (!isEnabled()) {
			return;
		}
		Map timers = timerStatisticsInThread.get();
		Iterator i = timers.keySet().iterator();
		SortedSet out = new TreeSet(new Comparator() {

			public int compare(TimerStatistics o1, TimerStatistics o2) {
				return o2.elapsedTime.intValue() - o1.elapsedTime.intValue();
			}
		});
		while (i.hasNext()){
			String e = i.next();
			TimerStatistics t = timers.get(e);
			if (t.callCount.intValue() > 0 ){
				out.add(t);
			}
			i.remove();
		}
		for (TimerStatistics s:out){
			System.out.println(s.getStatistics());
		}
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy