]> git.ipfire.org Git - thirdparty/squid.git/blame - src/StatHist.cc
Moved some more typedefs to StatHist.h
[thirdparty/squid.git] / src / StatHist.cc
CommitLineData
2ac76861 1
5625c032 2/*
5625c032 3 * DEBUG: section 62 Generic Histogram
4 * AUTHOR: Duane Wessels
5 *
2b6662ba 6 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 7 * ----------------------------------------------------------
5625c032 8 *
2b6662ba 9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
5625c032 17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
26ac0430 22 *
5625c032 23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
26ac0430 27 *
5625c032 28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
cbdec147 30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 31 *
5625c032 32 */
33
a343943f 34#include "config.h"
00a7574e 35#include "StatHist.h"
5625c032 36
37/* Local functions */
ba4f8e5a 38static StatHistBinDumper statHistBinDumper;
6617702a 39
20efa1c2
AJ
40namespace Math
41{
6617702a
AJ
42hbase_f Log;
43hbase_f Exp;
44hbase_f Null;
20efa1c2 45};
5625c032 46
47/* low level init, higher level functions has less params */
406c0a08
FC
48void
49StatHist::init(int capacity_, hbase_f * val_in_, hbase_f * val_out_, double min_, double max_)
5625c032 50{
406c0a08
FC
51 assert(capacity_ > 0);
52 assert(val_in_ && val_out_);
2f266e7a 53 /* check before we divide to get scale */
406c0a08
FC
54 assert(val_in_(max_ - min_) > 0);
55 min = min_;
56 max = max_;
57 capacity = capacity_;
58 val_in = val_in_;
59 val_out = val_out_;
a343943f 60 bins = static_cast<int *>(xcalloc(capacity, sizeof(int)));
406c0a08 61 scale = capacity / val_in(max - min);
9a2c68b2 62
2f266e7a 63 /* check that functions are valid */
64 /* a min value should go into bin[0] */
3da5974d 65 assert(findBin(min) == 0);
2f266e7a 66 /* a max value should go into the last bin */
3da5974d 67 assert(findBin(max) == capacity - 1);
2f266e7a 68 /* it is hard to test val_out, here is a crude test */
406c0a08 69 assert(((int) floor(0.99 + val(0) - min)) == 0);
5625c032 70}
71
72void
2ebbe7a4 73StatHist::clear()
5625c032 74{
2a38d231
FC
75 for(int i=0;i<capacity;++i)
76 bins[i]=0;
77}
78
79StatHist::~StatHist()
80{
81 if (bins != NULL) {
82 xfree(bins);
83 bins = NULL;
84 }
5625c032 85}
86
406c0a08
FC
87StatHist&
88StatHist::operator =(const StatHist & src)
89{
a343943f
FC
90 assert(src.bins != NULL); // TODO: remove after initializing bins at construction time
91 if (capacity != src.capacity) {
92 // need to resize.
93 xfree(bins);
94 bins = static_cast<int *>(xcalloc(src.capacity, sizeof(int)));
95 capacity=src.capacity;
96
97 }
98 min=src.min;
99 max=src.max;
100 scale=src.scale;
101 val_in=src.val_in;
102 val_out=src.val_out;
406c0a08
FC
103 memcpy(bins,src.bins,capacity*sizeof(*bins));
104 return *this;
105}
106
5625c032 107void
f30f7998 108StatHist::count(double val)
5625c032 109{
3da5974d 110 const int bin = findBin(val);
f30f7998
FC
111 assert(bins); /* make sure it got initialized */
112 assert(0 <= bin && bin < capacity);
113 ++bins[bin];
5625c032 114}
115
3da5974d
FC
116int
117StatHist::findBin(double v)
5625c032 118{
119 int bin;
62e76326 120
3da5974d 121 v -= min; /* offset */
62e76326 122
41587298 123 if (v <= 0.0) /* too small */
62e76326 124 return 0;
125
3da5974d 126 bin = (int) floor(scale * val_in(v) + 0.5);
62e76326 127
2ac76861 128 if (bin < 0) /* should not happen */
a343943f 129 return 0;
62e76326 130
3da5974d
FC
131 if (bin >= capacity) /* too big */
132 bin = capacity - 1;
62e76326 133
5625c032 134 return bin;
135}
136
5eeda86d
FC
137double
138StatHist::val(int bin) const
5625c032 139{
5eeda86d 140 return val_out((double) bin / scale) + min;
5625c032 141}
142
143double
3888201e 144statHistDeltaMedian(const StatHist & A, const StatHist & B)
04a28d46 145{
a343943f 146 return statHistDeltaPctile(A, B, 0.5);
04a28d46 147}
148
149double
3888201e 150statHistDeltaPctile(const StatHist & A, const StatHist & B, double pctile)
4fa5ccf4 151{
a343943f 152 return A.deltaPctile(B, pctile);
4fa5ccf4
FC
153}
154
155double
156StatHist::deltaPctile(const StatHist & B, double pctile) const
5625c032 157{
158 int i;
159 int s1 = 0;
160 int h = 0;
161 int a = 0;
162 int b = 0;
163 int I = 0;
4fa5ccf4 164 int J = capacity;
5625c032 165 int K;
166 double f;
62e76326 167
4fa5ccf4 168 assert(capacity == B.capacity);
5eeda86d 169
a343943f 170 int *D = static_cast<int *>(xcalloc(capacity, sizeof(int)));
5eeda86d 171
4fa5ccf4
FC
172 for (i = 0; i < capacity; ++i) {
173 D[i] = B.bins[i] - bins[i];
62e76326 174 assert(D[i] >= 0);
5625c032 175 }
62e76326 176
4fa5ccf4 177 for (i = 0; i < capacity; ++i)
62e76326 178 s1 += D[i];
179
04a28d46 180 h = int(s1 * pctile);
62e76326 181
4fa5ccf4 182 for (i = 0; i < capacity; ++i) {
62e76326 183 J = i;
184 b += D[J];
185
186 if (a <= h && h <= b)
187 break;
188
189 I = i;
190
191 a += D[I];
5625c032 192 }
62e76326 193
5625c032 194 xfree(D);
62e76326 195
5625c032 196 if (s1 == 0)
62e76326 197 return 0.0;
198
6a6c3b50 199 if (a > h)
62e76326 200 return 0.0;
201
6a6c3b50 202 if (a >= b)
62e76326 203 return 0.0;
204
6a6c3b50 205 if (I >= J)
62e76326 206 return 0.0;
207
5625c032 208 f = (h - a) / (b - a);
62e76326 209
9a2c68b2 210 K = (int) floor(f * (double) (J - I) + I);
62e76326 211
4fa5ccf4 212 return val(K);
5625c032 213}
214
215static void
216statHistBinDumper(StoreEntry * sentry, int idx, double val, double size, int count)
217{
218 if (count)
62e76326 219 storeAppendPrintf(sentry, "\t%3d/%f\t%d\t%f\n",
220 idx, val, count, count / size);
5625c032 221}
222
223void
96886986 224StatHist::dump(StoreEntry * sentry, StatHistBinDumper * bd) const
5625c032 225{
226 int i;
96886986 227 double left_border = min;
62e76326 228
5625c032 229 if (!bd)
62e76326 230 bd = statHistBinDumper;
231
96886986
FC
232 for (i = 0; i < capacity; ++i) {
233 const double right_border = val(i + 1);
62e76326 234 assert(right_border - left_border > 0.0);
96886986 235 bd(sentry, i, left_border, right_border - left_border, bins[i]);
62e76326 236 left_border = right_border;
5625c032 237 }
238}
239
240/* log based histogram */
853310e4 241double
20efa1c2 242Math::Log(double x)
2ac76861 243{
9689d97c 244 assert((x + 1.0) >= 0.0);
245 return log(x + 1.0);
2ac76861 246}
853310e4 247
853310e4 248double
20efa1c2 249Math::Exp(double x)
2ac76861 250{
9689d97c 251 return exp(x) - 1.0;
2ac76861 252}
853310e4 253
97d30a2e
FC
254void
255StatHist::logInit(int capacity, double min, double max)
256{
257 init(capacity, Math::Log, Math::Exp, min, max);
258}
259
5625c032 260/* linear histogram for enums */
261/* we want to be have [-1,last_enum+1] range to track out of range enums */
853310e4 262double
20efa1c2 263Math::Null(double x)
2ac76861 264{
265 return x;
266}
ba4f8e5a 267
d982012a
FC
268void
269StatHist::enumInit(int last_enum)
270{
a343943f 271 init(last_enum + 3, Math::Null, Math::Null, -1.0, (2.0 + last_enum));
d982012a
FC
272}
273
173d54ab 274void
ba4f8e5a 275statHistEnumDumper(StoreEntry * sentry, int idx, double val, double size, int count)
173d54ab 276{
277 if (count)
62e76326 278 storeAppendPrintf(sentry, "%2d\t %5d\t %5d\n",
279 idx, (int) val, count);
173d54ab 280}
ba4f8e5a 281
ba4f8e5a 282void
283statHistIntDumper(StoreEntry * sentry, int idx, double val, double size, int count)
284{
285 if (count)
62e76326 286 storeAppendPrintf(sentry, "%9d\t%9d\n", (int) val, count);
ba4f8e5a 287}