StatisticsAccumulator.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25package com.sun.corba.se.spi.monitoring; 26 27import java.util.*; 28 29/** 30 * <p> 31 * 32 * @author Hemanth Puttaswamy 33 * </p> 34 * <p> 35 * StatisticsAccumulator accumulates the samples provided by the user and 36 * computes the value of minimum, maximum, sum and sample square sum. When 37 * the StatisticMonitoredAttribute calls getValue(), it will compute all 38 * the statistics for the collected samples (Which are Minimum, Maximum, 39 * Average, StandardDeviation) and provides a nice printable record as a 40 * String. 41 * 42 * Users can easily extend this class and provide the implementation of 43 * toString() method to format the stats as desired. By default all the stats 44 * are printed in a single line. 45 * </p> 46 */ 47public class StatisticsAccumulator { 48 49 /////////////////////////////////////// 50 // attributes 51 52 53 // Users can extend this class to get access to current Max value 54 protected double max = Double.MIN_VALUE; 55 56 // Users can extend this class to get access to current Min value 57 protected double min = Double.MAX_VALUE; 58 59 private double sampleSum; 60 61 private double sampleSquareSum; 62 63 private long sampleCount; 64 65 protected String unit; 66 67 68 69 /////////////////////////////////////// 70 // operations 71 72 73 74/** 75 * <p> 76 * User will use this method to just register a sample with the 77 * StatisticsAccumulator. This is the only method that User will use to 78 * expose the statistics, internally the StatisticMonitoredAttribute will 79 * collect the information when requested from the ASAdmin. 80 * </p> 81 * <p> 82 * 83 * </p> 84 * <p> 85 * 86 * @param value a double value to make it more precise 87 * </p> 88 */ 89 public void sample(double value) { 90 sampleCount++; 91 if( value < min ) min = value; 92 if( value > max) max = value; 93 sampleSum += value; 94 sampleSquareSum += (value * value); 95 } // end sample 96 97 98 99 /** 100 * Computes the Standard Statistic Results based on the samples collected 101 * so far and provides the complete value as a formatted String 102 */ 103 public String getValue( ) { 104 return toString(); 105 } 106 107 /** 108 * Users can extend StatisticsAccumulator to provide the complete 109 * Stats in the format they prefer, if the default format doesn't suffice. 110 */ 111 public String toString( ) { 112 return "Minimum Value = " + min + " " + unit + " " + 113 "Maximum Value = " + max + " " + unit + " " + 114 "Average Value = " + computeAverage() + " " + unit + " " + 115 "Standard Deviation = " + computeStandardDeviation() + " " + unit + 116 " " + "Samples Collected = " + sampleCount; 117 } 118 119 /** 120 * If users choose to custom format the stats. 121 */ 122 protected double computeAverage( ) { 123 return (sampleSum / sampleCount); 124 } 125 126 127 /** 128 * We use a derived Standard Deviation formula to compute SD. This way 129 * there is no need to hold on to all the samples provided. 130 * 131 * The method is protected to let users extend and format the results. 132 */ 133 protected double computeStandardDeviation( ) { 134 double sampleSumSquare = sampleSum * sampleSum; 135 return Math.sqrt( 136 (sampleSquareSum-((sampleSumSquare)/sampleCount))/(sampleCount-1)); 137 } 138 139/** 140 * <p> 141 * Construct the Statistics Accumulator by providing the unit as a String. 142 * The examples of units are "Hours", "Minutes", 143 * "Seconds", "MilliSeconds", "Micro Seconds" 144 * etc., 145 * </p> 146 * <p> 147 * 148 * @return a StatisticsAccumulator with ... 149 * </p> 150 * <p> 151 * @param unit a String representing the units for the samples collected 152 * </p> 153 */ 154 public StatisticsAccumulator( String unit ) { 155 this.unit = unit; 156 sampleCount = 0; 157 sampleSum = 0; 158 sampleSquareSum = 0; 159 } 160 161 162 /** 163 * Clears the samples and starts fresh on new samples. 164 */ 165 void clearState( ) { 166 min = Double.MAX_VALUE; 167 max = Double.MIN_VALUE; 168 sampleCount = 0; 169 sampleSum = 0; 170 sampleSquareSum = 0; 171 } 172 173 /** 174 * This is an internal API to test StatisticsAccumulator... 175 */ 176 public void unitTestValidate( String expectedUnit, double expectedMin, 177 double expectedMax, long expectedSampleCount, double expectedAverage, 178 double expectedStandardDeviation ) 179 { 180 if( !expectedUnit.equals( unit ) ){ 181 throw new RuntimeException( 182 "Unit is not same as expected Unit" + 183 "\nUnit = " + unit + "ExpectedUnit = " + expectedUnit ); 184 } 185 if( min != expectedMin ) { 186 throw new RuntimeException( 187 "Minimum value is not same as expected minimum value" + 188 "\nMin Value = " + min + "Expected Min Value = " + expectedMin); 189 } 190 if( max != expectedMax ) { 191 throw new RuntimeException( 192 "Maximum value is not same as expected maximum value" + 193 "\nMax Value = " + max + "Expected Max Value = " + expectedMax); 194 } 195 if( sampleCount != expectedSampleCount ) { 196 throw new RuntimeException( 197 "Sample count is not same as expected Sample Count" + 198 "\nSampleCount = " + sampleCount + "Expected Sample Count = " + 199 expectedSampleCount); 200 } 201 if( computeAverage() != expectedAverage ) { 202 throw new RuntimeException( 203 "Average is not same as expected Average" + 204 "\nAverage = " + computeAverage() + "Expected Average = " + 205 expectedAverage); 206 } 207 // We are computing Standard Deviation from two different methods 208 // for comparison. So, the values will not be the exact same to the last 209 // few digits. So, we are taking the difference and making sure that 210 // the difference is not greater than 1. 211 double difference = Math.abs( 212 computeStandardDeviation() - expectedStandardDeviation); 213 if( difference > 1 ) { 214 throw new RuntimeException( 215 "Standard Deviation is not same as expected Std Deviation" + 216 "\nStandard Dev = " + computeStandardDeviation() + 217 "Expected Standard Dev = " + expectedStandardDeviation); 218 } 219 } 220 221 222} // end StatisticsAccumulator 223