001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.util;
020:
021: import org.apache.jmeter.samplers.SampleResult;
022:
023: /**
024: * Class to calculate various items that don't require all previous results to be saved:
025: * - mean = average
026: * - standard deviation
027: * - minimum
028: * - maximum
029: */
030: public class Calculator {
031:
032: private double sum = 0;
033:
034: private double sumOfSquares = 0;
035:
036: private double mean = 0;
037:
038: private double deviation = 0;
039:
040: private int count = 0;
041:
042: private long bytes = 0;
043:
044: private long maximum = Long.MIN_VALUE;
045:
046: private long minimum = Long.MAX_VALUE;
047:
048: private int errors = 0;
049:
050: private final String label;
051:
052: public Calculator() {
053: this ("");
054: }
055:
056: public Calculator(String label) {
057: this .label = label;
058: }
059:
060: public void clear() {
061: maximum = Long.MIN_VALUE;
062: minimum = Long.MAX_VALUE;
063: sum = 0;
064: sumOfSquares = 0;
065: mean = 0;
066: deviation = 0;
067: count = 0;
068: }
069:
070: public void addValue(long newValue) {
071: addValue(newValue, 1);
072: }
073:
074: private void addValue(long newValue, int sampleCount) {
075: count += sampleCount;
076: minimum = Math.min(newValue, minimum);
077: maximum = Math.max(newValue, maximum);
078: double currentVal = newValue;
079: sum += currentVal;
080: sumOfSquares += currentVal * currentVal;
081: // Calculate each time, as likely to be called for each add
082: mean = sum / count;
083: deviation = Math.sqrt((sumOfSquares / count) - (mean * mean));
084: }
085:
086: public void addBytes(long newValue) {
087: bytes += newValue;
088: }
089:
090: private long startTime = 0;
091: private long elapsedTime = 0;
092:
093: public void addSample(SampleResult res) {
094: addBytes(res.getBytes());
095: addValue(res.getTime(), res.getSampleCount());
096: errors += res.getErrorCount(); // account for multiple samples
097: if (startTime == 0) {
098: startTime = res.getStartTime();
099: }
100: startTime = Math.min(startTime, res.getStartTime());
101: elapsedTime = Math.max(elapsedTime, res.getEndTime()
102: - startTime);
103: }
104:
105: public long getTotalBytes() {
106: return bytes;
107: }
108:
109: public double getMean() {
110: return mean;
111: }
112:
113: public Number getMeanAsNumber() {
114: return new Long((long) mean);
115: }
116:
117: public double getStandardDeviation() {
118: return deviation;
119: }
120:
121: public long getMin() {
122: return minimum;
123: }
124:
125: public long getMax() {
126: return maximum;
127: }
128:
129: public int getCount() {
130: return count;
131: }
132:
133: public String getLabel() {
134: return label;
135: }
136:
137: /**
138: * Returns the raw double value of the percentage of samples with errors
139: * that were recorded. (Between 0.0 and 1.0)
140: *
141: * @return the raw double value of the percentage of samples with errors
142: * that were recorded.
143: */
144: public double getErrorPercentage() {
145: double rval = 0.0;
146:
147: if (count == 0) {
148: return (rval);
149: }
150: rval = (double) errors / (double) count;
151: return (rval);
152: }
153:
154: /**
155: * Returns the throughput associated to this sampler in requests per second.
156: * May be slightly skewed because it takes the timestamps of the first and
157: * last samples as the total time passed, and the test may actually have
158: * started before that start time and ended after that end time.
159: */
160: public double getRate() {
161: if (elapsedTime == 0)
162: return 0.0;
163:
164: return ((double) count / (double) elapsedTime) * 1000;
165: }
166:
167: /**
168: * calculates the average page size, which means divide the bytes by number
169: * of samples.
170: *
171: * This is an ambiguous name, so:
172: * @deprecated use getAvgPageBytes() instead.
173: *
174: * @return average page size
175: */
176: public double getPageSize() {
177: if (count > 0 && bytes > 0) {
178: return (double) bytes / count;
179: }
180: return 0.0;
181: }
182:
183: /**
184: * calculates the average page size, which means divide the bytes by number
185: * of samples.
186: *
187: * @return average page size in bytes
188: */
189: public double getAvgPageBytes() {
190: if (count > 0 && bytes > 0) {
191: return (double) bytes / count;
192: }
193: return 0.0;
194: }
195:
196: /**
197: * Throughput in bytes / second
198: *
199: * @return throughput in bytes/second
200: */
201: public double getBytesPerSecond() {
202: if (elapsedTime > 0) {
203: return bytes / ((double) elapsedTime / 1000); // 1000 = millisecs/sec
204: }
205: return 0.0;
206: }
207:
208: /**
209: * Throughput in kilobytes / second
210: *
211: * @return Throughput in kilobytes / second
212: */
213: public double getKBPerSecond() {
214: return getBytesPerSecond() / 1024; // 1024=bytes per kb
215: }
216:
217: }
|