2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
15 static StatHistBinDumper statHistBinDumper
;
24 /* low level init, higher level functions has less params */
26 StatHist::init(unsigned int newCapacity
, hbase_f
* val_in_
, hbase_f
* val_out_
, double newMin
, double newMax
)
28 /* check before we divide to get scale_ */
29 assert(val_in_(newMax
- newMin
) > 0);
32 capacity_
= newCapacity
;
35 bins
= static_cast<bins_type
*>(xcalloc(capacity_
, sizeof(bins_type
)));
36 scale_
= capacity_
/ val_in(max_
- min_
);
39 StatHist::StatHist(const StatHist
&src
) :
41 capacity_(src
.capacity_
),
48 if (src
.bins
!=nullptr) {
49 bins
= static_cast<bins_type
*>(xcalloc(src
.capacity_
, sizeof(bins_type
)));
50 memcpy(bins
,src
.bins
,capacity_
*sizeof(*bins
));
55 StatHist::count(double v
)
57 if (bins
==nullptr) //do not count before initialization or after destruction
59 const unsigned int bin
= findBin(v
);
64 StatHist::findBin(double v
)
66 v
-= min_
; /* offset */
68 if (v
<= 0.0) /* too small */
72 double tmp_bin
=floor(scale_
* val_in(v
) + 0.5);
74 if (tmp_bin
< 0.0) // should not happen
76 bin
= static_cast <unsigned int>(tmp_bin
);
78 if (bin
>= capacity_
) /* too big */
85 StatHist::val(unsigned int bin
) const
87 return val_out((double) bin
/ scale_
) + min_
;
91 statHistDeltaMedian(const StatHist
& A
, const StatHist
& B
)
93 return statHistDeltaPctile(A
, B
, 0.5);
97 statHistDeltaPctile(const StatHist
& A
, const StatHist
& B
, double pctile
)
99 return A
.deltaPctile(B
, pctile
);
103 StatHist::deltaPctile(const StatHist
& B
, double pctile
) const
111 unsigned int J
= capacity_
;
115 assert(capacity_
== B
.capacity_
);
117 int *D
= static_cast<int *>(xcalloc(capacity_
, sizeof(int)));
119 for (i
= 0; i
< capacity_
; ++i
) {
120 D
[i
] = B
.bins
[i
] - bins
[i
];
124 for (i
= 0; i
< capacity_
; ++i
)
127 h
= int(s1
* pctile
);
129 for (i
= 0; i
< capacity_
; ++i
) {
133 if (a
<= h
&& h
<= b
)
155 f
= (h
- a
) / (b
- a
);
157 K
= (unsigned int) floor(f
* (double) (J
- I
) + I
);
163 statHistBinDumper(StoreEntry
* sentry
, int idx
, double val
, double size
, int count
)
166 storeAppendPrintf(sentry
, "\t%3d/%f\t%d\t%f\n",
167 idx
, val
, count
, count
/ size
);
171 StatHist::dump(StoreEntry
* sentry
, StatHistBinDumper
* bd
) const
173 double left_border
= min_
;
176 bd
= statHistBinDumper
;
178 for (unsigned int i
= 0; i
< capacity_
; ++i
) {
179 const double right_border
= val(i
+ 1);
180 assert(right_border
- left_border
> 0.0);
181 bd(sentry
, i
, left_border
, right_border
- left_border
, bins
[i
]);
182 left_border
= right_border
;
187 StatHist::operator += (const StatHist
&B
)
189 Must(capacity_
== B
.capacity_
);
190 Must(min_
== B
.min_
);
191 Must(max_
== B
.max_
);
193 if (B
.bins
== nullptr) { // B was not yet initializted
196 if (bins
== nullptr) { // this histogram was not yet initialized
200 for (unsigned int i
= 0; i
< capacity_
; ++i
) {
201 bins
[i
] += B
.bins
[i
];
206 /* log based histogram */
210 assert((x
+ 1.0) >= 0.0);
221 StatHist::logInit(unsigned int capacity
, double min
, double max
)
223 init(capacity
, Math::Log
, Math::Exp
, min
, max
);
226 /* linear histogram for enums */
227 /* we want to be have [-1,last_enum+1] range to track out of range enums */
235 StatHist::enumInit(unsigned int last_enum
)
237 init(last_enum
+ 3, Math::Null
, Math::Null
, -1.0, (2.0 + last_enum
));
241 statHistEnumDumper(StoreEntry
* sentry
, int idx
, double val
, double, int count
)
244 storeAppendPrintf(sentry
, "%2d\t %5d\t %5d\n",
245 idx
, (int) val
, count
);
249 statHistIntDumper(StoreEntry
* sentry
, int, double val
, double, int count
)
252 storeAppendPrintf(sentry
, "%9d\t%9d\n", (int) val
, count
);