001: /*
002: * Copyright (c) 2002 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.util;
026:
027: import java.util.*;
028:
029: public class StatsGatherer {
030:
031: private Hashtable histogram;
032: private int bucketSize;
033: private String name;
034: private String tag;
035: private double mean = -1;
036:
037: private int skipSamples;
038: private int skip = 0;
039: public int num = 0;
040: public double maxVal = 0;
041: public double minVal = Double.MAX_VALUE;
042: public double cumulativeVal = 0;
043:
044: private static Hashtable sgTbl = new Hashtable();
045:
046: public StatsGatherer(String name, String tag, int bucketSize,
047: int skipSamples) {
048: this .name = name;
049: this .tag = tag;
050: this .bucketSize = bucketSize;
051: this .skipSamples = skipSamples;
052: if (bucketSize != 0) {
053: histogram = new Hashtable(1);
054: }
055: sgTbl.put(name, this );
056: }
057:
058: public StatsGatherer(String name, String tag, int bucketSize) {
059: this (name, tag, bucketSize, 0);
060: }
061:
062: public static StatsGatherer lookup(String name) {
063: return (StatsGatherer) sgTbl.get(name);
064: }
065:
066: public static Enumeration lookupAll() {
067: return sgTbl.elements();
068: }
069:
070: public static void dumpAll() {
071: Enumeration e = lookupAll();
072: while (e.hasMoreElements()) {
073: StatsGatherer sg = (StatsGatherer) e.nextElement();
074: sg.dumpHistogram();
075: }
076: }
077:
078: public synchronized void reset() {
079: this .num = 0;
080: this .maxVal = 0;
081: this .minVal = Double.MAX_VALUE;
082: this .cumulativeVal = 0;
083: if (bucketSize != 0) {
084: histogram = new Hashtable(1);
085: }
086: }
087:
088: public synchronized void add(double val) {
089: if (skip < skipSamples) {
090: skip++;
091: return;
092: }
093:
094: num++;
095:
096: if (val > maxVal)
097: maxVal = val;
098: if (val < minVal)
099: minVal = val;
100: cumulativeVal += val;
101:
102: if (bucketSize != 0) {
103: Integer ct = new Integer((int) val / bucketSize);
104: Integer bval = (Integer) histogram.remove(ct);
105:
106: if (bval == null) {
107: histogram.put(ct, new Integer(1));
108: } else {
109: bval = new Integer(bval.intValue() + 1);
110: histogram.put(ct, bval);
111: }
112: }
113: }
114:
115: public synchronized void dumpHistogram() {
116: System.err.println("=== Histogram dump of StatsGatherer: "
117: + name + " ===");
118:
119: TreeSet ts = new TreeSet(new Comparator() {
120: public int compare(Object o1, Object o2) {
121: Integer i1 = (Integer) o1;
122: Integer i2 = (Integer) o2;
123: if (i1.intValue() == i2.intValue())
124: return 0;
125: else if (i1.intValue() < i2.intValue())
126: return -1;
127: else
128: return 1;
129: }
130: });
131:
132: ts.addAll(histogram.keySet());
133:
134: Object arr[] = ts.toArray();
135: for (int i = 0; i < arr.length; i++) {
136: Integer bucket = (Integer) arr[i];
137: int time = bucket.intValue() * bucketSize;
138: int val = ((Integer) histogram.get(bucket)).intValue();
139: //System.err.println(tag+" "+time+" ms "+MDWUtil.format(val)+" count "+MDWUtil.format((val*100.0)/(num*1.0))+" pct");
140: }
141: System.err.println("=== Summary of StatsGatherer: " + name
142: + " ===");
143: System.err.println(tag + ": num " + num + " avg " + mean()
144: + " max " + max() + " 90th " + percentile(0.9));
145: System.err.println("=== End of summmary for StatsGatherer: "
146: + name + " ===");
147: System.err.println("\n");
148: }
149:
150: public synchronized int num() {
151: return num;
152: }
153:
154: public synchronized double mean() {
155: if (num == 0)
156: return 0.0;
157: return (cumulativeVal * 1.0) / num;
158: }
159:
160: public synchronized double min() {
161: return minVal;
162: }
163:
164: public synchronized double max() {
165: return maxVal;
166: }
167:
168: public synchronized double percentile(double pct) {
169: if (num == 0)
170: return 0.0;
171: double data[] = new double[num];
172: int n = 0;
173: Enumeration e = histogram.keys();
174: while (e.hasMoreElements()) {
175: Integer bucket = (Integer) e.nextElement();
176: int time = bucket.intValue() * bucketSize;
177: int val = ((Integer) histogram.get(bucket)).intValue();
178: for (int j = 0; j < val; j++) {
179: data[n++] = time;
180: }
181: }
182: Arrays.sort(data);
183: int index = (int) (data.length * pct);
184: return data[index];
185: }
186:
187: }
|