package com.zillabyte.motherbrain.benchmarking; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import org.apache.log4j.Logger; import org.codehaus.plexus.util.StringUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.zillabyte.motherbrain.utils.Utils; public class MovingBenchmarker extends Benchmark { /** * */ private static final long serialVersionUID = -1763550105106202667L; private static final int WINDOW_SIZE = 1000; private static final long REPORT_PERIOD = 1000L * 10; private static Logger _log = Utils.getLogger(MovingBenchmarker.class); private static Map<String, DescriptiveStatistics> _buffer = Maps.newHashMap(); private static Map<String, Map<Thread, Long>> _starts = Maps.newHashMap(); private static ScheduledFuture<?> _future = null; public MovingBenchmarker() { synchronized(MovingBenchmarker.class) { if (_future == null) { _future = Utils.timerFromPool(REPORT_PERIOD, new Runnable() { @Override public void run() { _log.info("-= BEGIN BENCHMARK REPORT =-"); for(String s : StringUtils.split(createReport(), "\n")) { _log.info(s); } _log.info("-= END BENCHMARK REPORT =-"); } }); } } } /** * * @param scope * @param name */ @Override public void begin(String name) { getStart(name).put(Thread.currentThread(), System.currentTimeMillis()); } private static Map<Thread, Long> getStart(String name) { if (_starts.containsKey(name) == false) { _starts.put(name, new HashMap<Thread, Long>()); } return _starts.get(name); } /*** * * @param scope * @param name */ @Override public void end(String name) { Long start = getStart(name).get(Thread.currentThread()); if (start == null) throw new IllegalStateException("benchmark.end() called without start(): " + name); if (_buffer.containsKey(name) == false) { _buffer.put(name, new DescriptiveStatistics(WINDOW_SIZE)); } _buffer.get(name).addValue(System.currentTimeMillis() - start); } public String createReport() { int rightPad = 50; StringBuilder sb = new StringBuilder(); ArrayList<Entry<String, DescriptiveStatistics>> list = Lists.newArrayList(_buffer.entrySet()); Collections.sort(list, new Comparator<Entry<String, DescriptiveStatistics>>() { @Override public int compare(Entry<String, DescriptiveStatistics> o1, Entry<String, DescriptiveStatistics> o2) { return o1.getKey().compareTo(o2.getKey()); } }); for(Entry<String, DescriptiveStatistics> e : list) { DescriptiveStatistics d = e.getValue(); sb.append(StringUtils.rightPad("* " + e.getKey() + " (" + d.getWindowSize() + ")", rightPad, ".")); sb.append("mean: " + d.getMean() + "ms\n"); sb.append(StringUtils.rightPad("", rightPad)); sb.append("max: " + d.getMax() + "ms\n"); sb.append(StringUtils.rightPad("", rightPad)); sb.append("min: " + d.getMin() + "ms\n"); } return sb.toString(); } }