statistics.hh (7811:a8fc35183c10) statistics.hh (7823:dac01f14f20f)
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31/** @file
32 * Declaration of Statistics objects.
33 */
34
35/**
36* @todo
37*
38* Generalized N-dimensinal vector
39* documentation
40* key stats
41* interval stats
42* -- these both can use the same function that prints out a
43* specific set of stats
44* VectorStandardDeviation totals
45* Document Namespaces
46*/
47#ifndef __BASE_STATISTICS_HH__
48#define __BASE_STATISTICS_HH__
49
50#include <algorithm>
51#include <cassert>
52#ifdef __SUNPRO_CC
53#include <math.h>
54#endif
55#include <cmath>
56#include <functional>
57#include <iosfwd>
58#include <list>
59#include <string>
60#include <vector>
61
62#include "base/cast.hh"
63#include "base/cprintf.hh"
64#include "base/intmath.hh"
65#include "base/refcnt.hh"
66#include "base/stats/info.hh"
67#include "base/stats/types.hh"
68#include "base/stats/visit.hh"
69#include "base/str.hh"
70#include "base/types.hh"
71
72class Callback;
73
74/** The current simulated tick. */
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31/** @file
32 * Declaration of Statistics objects.
33 */
34
35/**
36* @todo
37*
38* Generalized N-dimensinal vector
39* documentation
40* key stats
41* interval stats
42* -- these both can use the same function that prints out a
43* specific set of stats
44* VectorStandardDeviation totals
45* Document Namespaces
46*/
47#ifndef __BASE_STATISTICS_HH__
48#define __BASE_STATISTICS_HH__
49
50#include <algorithm>
51#include <cassert>
52#ifdef __SUNPRO_CC
53#include <math.h>
54#endif
55#include <cmath>
56#include <functional>
57#include <iosfwd>
58#include <list>
59#include <string>
60#include <vector>
61
62#include "base/cast.hh"
63#include "base/cprintf.hh"
64#include "base/intmath.hh"
65#include "base/refcnt.hh"
66#include "base/stats/info.hh"
67#include "base/stats/types.hh"
68#include "base/stats/visit.hh"
69#include "base/str.hh"
70#include "base/types.hh"
71
72class Callback;
73
74/** The current simulated tick. */
75extern Tick curTick;
75extern Tick curTick();
76
77/* A namespace for all of the Statistics */
78namespace Stats {
79
80template <class Stat, class Base>
81class InfoProxy : public Base
82{
83 protected:
84 Stat &s;
85
86 public:
87 InfoProxy(Stat &stat) : s(stat) {}
88
89 bool check() const { return s.check(); }
90 void prepare() { s.prepare(); }
91 void reset() { s.reset(); }
92 void
93 visit(Visit &visitor)
94 {
95 visitor.visit(*static_cast<Base *>(this));
96 }
97 bool zero() const { return s.zero(); }
98};
99
100template <class Stat>
101class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
102{
103 public:
104 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
105
106 Counter value() const { return this->s.value(); }
107 Result result() const { return this->s.result(); }
108 Result total() const { return this->s.total(); }
109};
110
111template <class Stat>
112class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
113{
114 protected:
115 mutable VCounter cvec;
116 mutable VResult rvec;
117
118 public:
119 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
120
121 size_type size() const { return this->s.size(); }
122
123 VCounter &
124 value() const
125 {
126 this->s.value(cvec);
127 return cvec;
128 }
129
130 const VResult &
131 result() const
132 {
133 this->s.result(rvec);
134 return rvec;
135 }
136
137 Result total() const { return this->s.total(); }
138};
139
140template <class Stat>
141class DistInfoProxy : public InfoProxy<Stat, DistInfo>
142{
143 public:
144 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
145};
146
147template <class Stat>
148class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
149{
150 public:
151 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
152
153 size_type size() const { return this->s.size(); }
154};
155
156template <class Stat>
157class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
158{
159 public:
160 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
161};
162
163struct StorageParams
164{
165 virtual ~StorageParams();
166};
167
168class InfoAccess
169{
170 protected:
171 /** Set up an info class for this statistic */
172 void setInfo(Info *info);
173 /** Save Storage class parameters if any */
174 void setParams(const StorageParams *params);
175 /** Save Storage class parameters if any */
176 void setInit();
177
178 /** Grab the information class for this statistic */
179 Info *info();
180 /** Grab the information class for this statistic */
181 const Info *info() const;
182
183 public:
184 /**
185 * Reset the stat to the default state.
186 */
187 void reset() { }
188
189 /**
190 * @return true if this stat has a value and satisfies its
191 * requirement as a prereq
192 */
193 bool zero() const { return true; }
194
195 /**
196 * Check that this stat has been set up properly and is ready for
197 * use
198 * @return true for success
199 */
200 bool check() const { return true; }
201};
202
203template <class Derived, template <class> class InfoProxyType>
204class DataWrap : public InfoAccess
205{
206 public:
207 typedef InfoProxyType<Derived> Info;
208
209 protected:
210 Derived &self() { return *static_cast<Derived *>(this); }
211
212 protected:
213 Info *
214 info()
215 {
216 return safe_cast<Info *>(InfoAccess::info());
217 }
218
219 public:
220 const Info *
221 info() const
222 {
223 return safe_cast<const Info *>(InfoAccess::info());
224 }
225
226 protected:
227 /**
228 * Copy constructor, copies are not allowed.
229 */
230 DataWrap(const DataWrap &stat);
231
232 /**
233 * Can't copy stats.
234 */
235 void operator=(const DataWrap &);
236
237 public:
238 DataWrap()
239 {
240 this->setInfo(new Info(self()));
241 }
242
243 /**
244 * Set the name and marks this stat to print at the end of simulation.
245 * @param name The new name.
246 * @return A reference to this stat.
247 */
248 Derived &
249 name(const std::string &name)
250 {
251 Info *info = this->info();
252 info->setName(name);
253 info->flags.set(display);
254 return this->self();
255 }
256 const std::string &name() const { return this->info()->name; }
257
258 /**
259 * Set the description and marks this stat to print at the end of
260 * simulation.
261 * @param desc The new description.
262 * @return A reference to this stat.
263 */
264 Derived &
265 desc(const std::string &_desc)
266 {
267 this->info()->desc = _desc;
268 return this->self();
269 }
270
271 /**
272 * Set the precision and marks this stat to print at the end of simulation.
273 * @param _precision The new precision
274 * @return A reference to this stat.
275 */
276 Derived &
277 precision(int _precision)
278 {
279 this->info()->precision = _precision;
280 return this->self();
281 }
282
283 /**
284 * Set the flags and marks this stat to print at the end of simulation.
285 * @param f The new flags.
286 * @return A reference to this stat.
287 */
288 Derived &
289 flags(Flags _flags)
290 {
291 this->info()->flags.set(_flags);
292 return this->self();
293 }
294
295 /**
296 * Set the prerequisite stat and marks this stat to print at the end of
297 * simulation.
298 * @param prereq The prerequisite stat.
299 * @return A reference to this stat.
300 */
301 template <class Stat>
302 Derived &
303 prereq(const Stat &prereq)
304 {
305 this->info()->prereq = prereq.info();
306 return this->self();
307 }
308};
309
310template <class Derived, template <class> class InfoProxyType>
311class DataWrapVec : public DataWrap<Derived, InfoProxyType>
312{
313 public:
314 typedef InfoProxyType<Derived> Info;
315
316 // The following functions are specific to vectors. If you use them
317 // in a non vector context, you will get a nice compiler error!
318
319 /**
320 * Set the subfield name for the given index, and marks this stat to print
321 * at the end of simulation.
322 * @param index The subfield index.
323 * @param name The new name of the subfield.
324 * @return A reference to this stat.
325 */
326 Derived &
327 subname(off_type index, const std::string &name)
328 {
329 Derived &self = this->self();
330 Info *info = self.info();
331
332 std::vector<std::string> &subn = info->subnames;
333 if (subn.size() <= index)
334 subn.resize(index + 1);
335 subn[index] = name;
336 return self;
337 }
338
339 // The following functions are specific to 2d vectors. If you use
340 // them in a non vector context, you will get a nice compiler
341 // error because info doesn't have the right variables.
342
343 /**
344 * Set the subfield description for the given index and marks this stat to
345 * print at the end of simulation.
346 * @param index The subfield index.
347 * @param desc The new description of the subfield
348 * @return A reference to this stat.
349 */
350 Derived &
351 subdesc(off_type index, const std::string &desc)
352 {
353 Info *info = this->info();
354
355 std::vector<std::string> &subd = info->subdescs;
356 if (subd.size() <= index)
357 subd.resize(index + 1);
358 subd[index] = desc;
359
360 return this->self();
361 }
362
363 void
364 prepare()
365 {
366 Derived &self = this->self();
367 Info *info = this->info();
368
369 size_t size = self.size();
370 for (off_type i = 0; i < size; ++i)
371 self.data(i)->prepare(info);
372 }
373
374 void
375 reset()
376 {
377 Derived &self = this->self();
378 Info *info = this->info();
379
380 size_t size = self.size();
381 for (off_type i = 0; i < size; ++i)
382 self.data(i)->reset(info);
383 }
384};
385
386template <class Derived, template <class> class InfoProxyType>
387class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
388{
389 public:
390 typedef InfoProxyType<Derived> Info;
391
392 /**
393 * @warning This makes the assumption that if you're gonna subnames a 2d
394 * vector, you're subnaming across all y
395 */
396 Derived &
397 ysubnames(const char **names)
398 {
399 Derived &self = this->self();
400 Info *info = this->info();
401
402 info->y_subnames.resize(self.y);
403 for (off_type i = 0; i < self.y; ++i)
404 info->y_subnames[i] = names[i];
405 return self;
406 }
407
408 Derived &
409 ysubname(off_type index, const std::string &subname)
410 {
411 Derived &self = this->self();
412 Info *info = this->info();
413
414 assert(index < self.y);
415 info->y_subnames.resize(self.y);
416 info->y_subnames[index] = subname.c_str();
417 return self;
418 }
419
420 std::string
421 ysubname(off_type i) const
422 {
423 return this->info()->y_subnames[i];
424 }
425
426};
427
428//////////////////////////////////////////////////////////////////////
429//
430// Simple Statistics
431//
432//////////////////////////////////////////////////////////////////////
433
434/**
435 * Templatized storage and interface for a simple scalar stat.
436 */
437class StatStor
438{
439 private:
440 /** The statistic value. */
441 Counter data;
442
443 public:
444 struct Params : public StorageParams {};
445
446 public:
447 /**
448 * Builds this storage element and calls the base constructor of the
449 * datatype.
450 */
451 StatStor(Info *info)
452 : data(Counter())
453 { }
454
455 /**
456 * The the stat to the given value.
457 * @param val The new value.
458 */
459 void set(Counter val) { data = val; }
460 /**
461 * Increment the stat by the given value.
462 * @param val The new value.
463 */
464 void inc(Counter val) { data += val; }
465 /**
466 * Decrement the stat by the given value.
467 * @param val The new value.
468 */
469 void dec(Counter val) { data -= val; }
470 /**
471 * Return the value of this stat as its base type.
472 * @return The value of this stat.
473 */
474 Counter value() const { return data; }
475 /**
476 * Return the value of this stat as a result type.
477 * @return The value of this stat.
478 */
479 Result result() const { return (Result)data; }
480 /**
481 * Prepare stat data for dumping or serialization
482 */
483 void prepare(Info *info) { }
484 /**
485 * Reset stat value to default
486 */
487 void reset(Info *info) { data = Counter(); }
488
489 /**
490 * @return true if zero value
491 */
492 bool zero() const { return data == Counter(); }
493};
494
495/**
496 * Templatized storage and interface to a per-tick average stat. This keeps
497 * a current count and updates a total (count * ticks) when this count
498 * changes. This allows the quick calculation of a per tick count of the item
499 * being watched. This is good for keeping track of residencies in structures
500 * among other things.
501 */
502class AvgStor
503{
504 private:
505 /** The current count. */
506 Counter current;
507 /** The tick of the last reset */
508 Tick lastReset;
509 /** The total count for all tick. */
510 mutable Result total;
511 /** The tick that current last changed. */
512 mutable Tick last;
513
514 public:
515 struct Params : public StorageParams {};
516
517 public:
518 /**
519 * Build and initializes this stat storage.
520 */
521 AvgStor(Info *info)
522 : current(0), lastReset(0), total(0), last(0)
523 { }
524
525 /**
526 * Set the current count to the one provided, update the total and last
527 * set values.
528 * @param val The new count.
529 */
530 void
531 set(Counter val)
532 {
76
77/* A namespace for all of the Statistics */
78namespace Stats {
79
80template <class Stat, class Base>
81class InfoProxy : public Base
82{
83 protected:
84 Stat &s;
85
86 public:
87 InfoProxy(Stat &stat) : s(stat) {}
88
89 bool check() const { return s.check(); }
90 void prepare() { s.prepare(); }
91 void reset() { s.reset(); }
92 void
93 visit(Visit &visitor)
94 {
95 visitor.visit(*static_cast<Base *>(this));
96 }
97 bool zero() const { return s.zero(); }
98};
99
100template <class Stat>
101class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
102{
103 public:
104 ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
105
106 Counter value() const { return this->s.value(); }
107 Result result() const { return this->s.result(); }
108 Result total() const { return this->s.total(); }
109};
110
111template <class Stat>
112class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
113{
114 protected:
115 mutable VCounter cvec;
116 mutable VResult rvec;
117
118 public:
119 VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
120
121 size_type size() const { return this->s.size(); }
122
123 VCounter &
124 value() const
125 {
126 this->s.value(cvec);
127 return cvec;
128 }
129
130 const VResult &
131 result() const
132 {
133 this->s.result(rvec);
134 return rvec;
135 }
136
137 Result total() const { return this->s.total(); }
138};
139
140template <class Stat>
141class DistInfoProxy : public InfoProxy<Stat, DistInfo>
142{
143 public:
144 DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
145};
146
147template <class Stat>
148class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
149{
150 public:
151 VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
152
153 size_type size() const { return this->s.size(); }
154};
155
156template <class Stat>
157class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
158{
159 public:
160 Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
161};
162
163struct StorageParams
164{
165 virtual ~StorageParams();
166};
167
168class InfoAccess
169{
170 protected:
171 /** Set up an info class for this statistic */
172 void setInfo(Info *info);
173 /** Save Storage class parameters if any */
174 void setParams(const StorageParams *params);
175 /** Save Storage class parameters if any */
176 void setInit();
177
178 /** Grab the information class for this statistic */
179 Info *info();
180 /** Grab the information class for this statistic */
181 const Info *info() const;
182
183 public:
184 /**
185 * Reset the stat to the default state.
186 */
187 void reset() { }
188
189 /**
190 * @return true if this stat has a value and satisfies its
191 * requirement as a prereq
192 */
193 bool zero() const { return true; }
194
195 /**
196 * Check that this stat has been set up properly and is ready for
197 * use
198 * @return true for success
199 */
200 bool check() const { return true; }
201};
202
203template <class Derived, template <class> class InfoProxyType>
204class DataWrap : public InfoAccess
205{
206 public:
207 typedef InfoProxyType<Derived> Info;
208
209 protected:
210 Derived &self() { return *static_cast<Derived *>(this); }
211
212 protected:
213 Info *
214 info()
215 {
216 return safe_cast<Info *>(InfoAccess::info());
217 }
218
219 public:
220 const Info *
221 info() const
222 {
223 return safe_cast<const Info *>(InfoAccess::info());
224 }
225
226 protected:
227 /**
228 * Copy constructor, copies are not allowed.
229 */
230 DataWrap(const DataWrap &stat);
231
232 /**
233 * Can't copy stats.
234 */
235 void operator=(const DataWrap &);
236
237 public:
238 DataWrap()
239 {
240 this->setInfo(new Info(self()));
241 }
242
243 /**
244 * Set the name and marks this stat to print at the end of simulation.
245 * @param name The new name.
246 * @return A reference to this stat.
247 */
248 Derived &
249 name(const std::string &name)
250 {
251 Info *info = this->info();
252 info->setName(name);
253 info->flags.set(display);
254 return this->self();
255 }
256 const std::string &name() const { return this->info()->name; }
257
258 /**
259 * Set the description and marks this stat to print at the end of
260 * simulation.
261 * @param desc The new description.
262 * @return A reference to this stat.
263 */
264 Derived &
265 desc(const std::string &_desc)
266 {
267 this->info()->desc = _desc;
268 return this->self();
269 }
270
271 /**
272 * Set the precision and marks this stat to print at the end of simulation.
273 * @param _precision The new precision
274 * @return A reference to this stat.
275 */
276 Derived &
277 precision(int _precision)
278 {
279 this->info()->precision = _precision;
280 return this->self();
281 }
282
283 /**
284 * Set the flags and marks this stat to print at the end of simulation.
285 * @param f The new flags.
286 * @return A reference to this stat.
287 */
288 Derived &
289 flags(Flags _flags)
290 {
291 this->info()->flags.set(_flags);
292 return this->self();
293 }
294
295 /**
296 * Set the prerequisite stat and marks this stat to print at the end of
297 * simulation.
298 * @param prereq The prerequisite stat.
299 * @return A reference to this stat.
300 */
301 template <class Stat>
302 Derived &
303 prereq(const Stat &prereq)
304 {
305 this->info()->prereq = prereq.info();
306 return this->self();
307 }
308};
309
310template <class Derived, template <class> class InfoProxyType>
311class DataWrapVec : public DataWrap<Derived, InfoProxyType>
312{
313 public:
314 typedef InfoProxyType<Derived> Info;
315
316 // The following functions are specific to vectors. If you use them
317 // in a non vector context, you will get a nice compiler error!
318
319 /**
320 * Set the subfield name for the given index, and marks this stat to print
321 * at the end of simulation.
322 * @param index The subfield index.
323 * @param name The new name of the subfield.
324 * @return A reference to this stat.
325 */
326 Derived &
327 subname(off_type index, const std::string &name)
328 {
329 Derived &self = this->self();
330 Info *info = self.info();
331
332 std::vector<std::string> &subn = info->subnames;
333 if (subn.size() <= index)
334 subn.resize(index + 1);
335 subn[index] = name;
336 return self;
337 }
338
339 // The following functions are specific to 2d vectors. If you use
340 // them in a non vector context, you will get a nice compiler
341 // error because info doesn't have the right variables.
342
343 /**
344 * Set the subfield description for the given index and marks this stat to
345 * print at the end of simulation.
346 * @param index The subfield index.
347 * @param desc The new description of the subfield
348 * @return A reference to this stat.
349 */
350 Derived &
351 subdesc(off_type index, const std::string &desc)
352 {
353 Info *info = this->info();
354
355 std::vector<std::string> &subd = info->subdescs;
356 if (subd.size() <= index)
357 subd.resize(index + 1);
358 subd[index] = desc;
359
360 return this->self();
361 }
362
363 void
364 prepare()
365 {
366 Derived &self = this->self();
367 Info *info = this->info();
368
369 size_t size = self.size();
370 for (off_type i = 0; i < size; ++i)
371 self.data(i)->prepare(info);
372 }
373
374 void
375 reset()
376 {
377 Derived &self = this->self();
378 Info *info = this->info();
379
380 size_t size = self.size();
381 for (off_type i = 0; i < size; ++i)
382 self.data(i)->reset(info);
383 }
384};
385
386template <class Derived, template <class> class InfoProxyType>
387class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
388{
389 public:
390 typedef InfoProxyType<Derived> Info;
391
392 /**
393 * @warning This makes the assumption that if you're gonna subnames a 2d
394 * vector, you're subnaming across all y
395 */
396 Derived &
397 ysubnames(const char **names)
398 {
399 Derived &self = this->self();
400 Info *info = this->info();
401
402 info->y_subnames.resize(self.y);
403 for (off_type i = 0; i < self.y; ++i)
404 info->y_subnames[i] = names[i];
405 return self;
406 }
407
408 Derived &
409 ysubname(off_type index, const std::string &subname)
410 {
411 Derived &self = this->self();
412 Info *info = this->info();
413
414 assert(index < self.y);
415 info->y_subnames.resize(self.y);
416 info->y_subnames[index] = subname.c_str();
417 return self;
418 }
419
420 std::string
421 ysubname(off_type i) const
422 {
423 return this->info()->y_subnames[i];
424 }
425
426};
427
428//////////////////////////////////////////////////////////////////////
429//
430// Simple Statistics
431//
432//////////////////////////////////////////////////////////////////////
433
434/**
435 * Templatized storage and interface for a simple scalar stat.
436 */
437class StatStor
438{
439 private:
440 /** The statistic value. */
441 Counter data;
442
443 public:
444 struct Params : public StorageParams {};
445
446 public:
447 /**
448 * Builds this storage element and calls the base constructor of the
449 * datatype.
450 */
451 StatStor(Info *info)
452 : data(Counter())
453 { }
454
455 /**
456 * The the stat to the given value.
457 * @param val The new value.
458 */
459 void set(Counter val) { data = val; }
460 /**
461 * Increment the stat by the given value.
462 * @param val The new value.
463 */
464 void inc(Counter val) { data += val; }
465 /**
466 * Decrement the stat by the given value.
467 * @param val The new value.
468 */
469 void dec(Counter val) { data -= val; }
470 /**
471 * Return the value of this stat as its base type.
472 * @return The value of this stat.
473 */
474 Counter value() const { return data; }
475 /**
476 * Return the value of this stat as a result type.
477 * @return The value of this stat.
478 */
479 Result result() const { return (Result)data; }
480 /**
481 * Prepare stat data for dumping or serialization
482 */
483 void prepare(Info *info) { }
484 /**
485 * Reset stat value to default
486 */
487 void reset(Info *info) { data = Counter(); }
488
489 /**
490 * @return true if zero value
491 */
492 bool zero() const { return data == Counter(); }
493};
494
495/**
496 * Templatized storage and interface to a per-tick average stat. This keeps
497 * a current count and updates a total (count * ticks) when this count
498 * changes. This allows the quick calculation of a per tick count of the item
499 * being watched. This is good for keeping track of residencies in structures
500 * among other things.
501 */
502class AvgStor
503{
504 private:
505 /** The current count. */
506 Counter current;
507 /** The tick of the last reset */
508 Tick lastReset;
509 /** The total count for all tick. */
510 mutable Result total;
511 /** The tick that current last changed. */
512 mutable Tick last;
513
514 public:
515 struct Params : public StorageParams {};
516
517 public:
518 /**
519 * Build and initializes this stat storage.
520 */
521 AvgStor(Info *info)
522 : current(0), lastReset(0), total(0), last(0)
523 { }
524
525 /**
526 * Set the current count to the one provided, update the total and last
527 * set values.
528 * @param val The new count.
529 */
530 void
531 set(Counter val)
532 {
533 total += current * (curTick - last);
534 last = curTick;
533 total += current * (curTick() - last);
534 last = curTick();
535 current = val;
536 }
537
538 /**
539 * Increment the current count by the provided value, calls set.
540 * @param val The amount to increment.
541 */
542 void inc(Counter val) { set(current + val); }
543
544 /**
545 * Deccrement the current count by the provided value, calls set.
546 * @param val The amount to decrement.
547 */
548 void dec(Counter val) { set(current - val); }
549
550 /**
551 * Return the current count.
552 * @return The current count.
553 */
554 Counter value() const { return current; }
555
556 /**
557 * Return the current average.
558 * @return The current average.
559 */
560 Result
561 result() const
562 {
535 current = val;
536 }
537
538 /**
539 * Increment the current count by the provided value, calls set.
540 * @param val The amount to increment.
541 */
542 void inc(Counter val) { set(current + val); }
543
544 /**
545 * Deccrement the current count by the provided value, calls set.
546 * @param val The amount to decrement.
547 */
548 void dec(Counter val) { set(current - val); }
549
550 /**
551 * Return the current count.
552 * @return The current count.
553 */
554 Counter value() const { return current; }
555
556 /**
557 * Return the current average.
558 * @return The current average.
559 */
560 Result
561 result() const
562 {
563 assert(last == curTick);
564 return (Result)(total + current) / (Result)(curTick - lastReset + 1);
563 assert(last == curTick());
564 return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
565 }
566
567 /**
568 * @return true if zero value
569 */
570 bool zero() const { return total == 0.0; }
571
572 /**
573 * Prepare stat data for dumping or serialization
574 */
575 void
576 prepare(Info *info)
577 {
565 }
566
567 /**
568 * @return true if zero value
569 */
570 bool zero() const { return total == 0.0; }
571
572 /**
573 * Prepare stat data for dumping or serialization
574 */
575 void
576 prepare(Info *info)
577 {
578 total += current * (curTick - last);
579 last = curTick;
578 total += current * (curTick() - last);
579 last = curTick();
580 }
581
582 /**
583 * Reset stat value to default
584 */
585 void
586 reset(Info *info)
587 {
588 total = 0.0;
580 }
581
582 /**
583 * Reset stat value to default
584 */
585 void
586 reset(Info *info)
587 {
588 total = 0.0;
589 last = curTick;
590 lastReset = curTick;
589 last = curTick();
590 lastReset = curTick();
591 }
592
593};
594
595/**
596 * Implementation of a scalar stat. The type of stat is determined by the
597 * Storage template.
598 */
599template <class Derived, class Stor>
600class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
601{
602 public:
603 typedef Stor Storage;
604 typedef typename Stor::Params Params;
605
606 protected:
607 /** The storage of this stat. */
608 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
609
610 protected:
611 /**
612 * Retrieve the storage.
613 * @param index The vector index to access.
614 * @return The storage object at the given index.
615 */
616 Storage *
617 data()
618 {
619 return reinterpret_cast<Storage *>(storage);
620 }
621
622 /**
623 * Retrieve a const pointer to the storage.
624 * for the given index.
625 * @param index The vector index to access.
626 * @return A const pointer to the storage object at the given index.
627 */
628 const Storage *
629 data() const
630 {
631 return reinterpret_cast<const Storage *>(storage);
632 }
633
634 void
635 doInit()
636 {
637 new (storage) Storage(this->info());
638 this->setInit();
639 }
640
641 public:
642 /**
643 * Return the current value of this stat as its base type.
644 * @return The current value.
645 */
646 Counter value() const { return data()->value(); }
647
648 public:
649 ScalarBase()
650 {
651 this->doInit();
652 }
653
654 public:
655 // Common operators for stats
656 /**
657 * Increment the stat by 1. This calls the associated storage object inc
658 * function.
659 */
660 void operator++() { data()->inc(1); }
661 /**
662 * Decrement the stat by 1. This calls the associated storage object dec
663 * function.
664 */
665 void operator--() { data()->dec(1); }
666
667 /** Increment the stat by 1. */
668 void operator++(int) { ++*this; }
669 /** Decrement the stat by 1. */
670 void operator--(int) { --*this; }
671
672 /**
673 * Set the data value to the given value. This calls the associated storage
674 * object set function.
675 * @param v The new value.
676 */
677 template <typename U>
678 void operator=(const U &v) { data()->set(v); }
679
680 /**
681 * Increment the stat by the given value. This calls the associated
682 * storage object inc function.
683 * @param v The value to add.
684 */
685 template <typename U>
686 void operator+=(const U &v) { data()->inc(v); }
687
688 /**
689 * Decrement the stat by the given value. This calls the associated
690 * storage object dec function.
691 * @param v The value to substract.
692 */
693 template <typename U>
694 void operator-=(const U &v) { data()->dec(v); }
695
696 /**
697 * Return the number of elements, always 1 for a scalar.
698 * @return 1.
699 */
700 size_type size() const { return 1; }
701
702 Counter value() { return data()->value(); }
703
704 Result result() { return data()->result(); }
705
706 Result total() { return result(); }
707
708 bool zero() { return result() == 0.0; }
709
710 void reset() { data()->reset(this->info()); }
711 void prepare() { data()->prepare(this->info()); }
712};
713
714class ProxyInfo : public ScalarInfo
715{
716 public:
717 std::string str() const { return to_string(value()); }
718 size_type size() const { return 1; }
719 bool check() const { return true; }
720 void prepare() { }
721 void reset() { }
722 bool zero() const { return value() == 0; }
723
724 void visit(Visit &visitor) { visitor.visit(*this); }
725};
726
727template <class T>
728class ValueProxy : public ProxyInfo
729{
730 private:
731 T *scalar;
732
733 public:
734 ValueProxy(T &val) : scalar(&val) {}
735 Counter value() const { return *scalar; }
736 Result result() const { return *scalar; }
737 Result total() const { return *scalar; }
738};
739
740template <class T>
741class FunctorProxy : public ProxyInfo
742{
743 private:
744 T *functor;
745
746 public:
747 FunctorProxy(T &func) : functor(&func) {}
748 Counter value() const { return (*functor)(); }
749 Result result() const { return (*functor)(); }
750 Result total() const { return (*functor)(); }
751};
752
753template <class Derived>
754class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
755{
756 private:
757 ProxyInfo *proxy;
758
759 public:
760 ValueBase() : proxy(NULL) { }
761 ~ValueBase() { if (proxy) delete proxy; }
762
763 template <class T>
764 Derived &
765 scalar(T &value)
766 {
767 proxy = new ValueProxy<T>(value);
768 this->setInit();
769 return this->self();
770 }
771
772 template <class T>
773 Derived &
774 functor(T &func)
775 {
776 proxy = new FunctorProxy<T>(func);
777 this->setInit();
778 return this->self();
779 }
780
781 Counter value() { return proxy->value(); }
782 Result result() const { return proxy->result(); }
783 Result total() const { return proxy->total(); };
784 size_type size() const { return proxy->size(); }
785
786 std::string str() const { return proxy->str(); }
787 bool zero() const { return proxy->zero(); }
788 bool check() const { return proxy != NULL; }
789 void prepare() { }
790 void reset() { }
791};
792
793//////////////////////////////////////////////////////////////////////
794//
795// Vector Statistics
796//
797//////////////////////////////////////////////////////////////////////
798
799/**
800 * A proxy class to access the stat at a given index in a VectorBase stat.
801 * Behaves like a ScalarBase.
802 */
803template <class Stat>
804class ScalarProxy
805{
806 private:
807 /** Pointer to the parent Vector. */
808 Stat &stat;
809
810 /** The index to access in the parent VectorBase. */
811 off_type index;
812
813 public:
814 /**
815 * Return the current value of this stat as its base type.
816 * @return The current value.
817 */
818 Counter value() const { return stat.data(index)->value(); }
819
820 /**
821 * Return the current value of this statas a result type.
822 * @return The current value.
823 */
824 Result result() const { return stat.data(index)->result(); }
825
826 public:
827 /**
828 * Create and initialize this proxy, do not register it with the database.
829 * @param i The index to access.
830 */
831 ScalarProxy(Stat &s, off_type i)
832 : stat(s), index(i)
833 {
834 }
835
836 /**
837 * Create a copy of the provided ScalarProxy.
838 * @param sp The proxy to copy.
839 */
840 ScalarProxy(const ScalarProxy &sp)
841 : stat(sp.stat), index(sp.index)
842 {}
843
844 /**
845 * Set this proxy equal to the provided one.
846 * @param sp The proxy to copy.
847 * @return A reference to this proxy.
848 */
849 const ScalarProxy &
850 operator=(const ScalarProxy &sp)
851 {
852 stat = sp.stat;
853 index = sp.index;
854 return *this;
855 }
856
857 public:
858 // Common operators for stats
859 /**
860 * Increment the stat by 1. This calls the associated storage object inc
861 * function.
862 */
863 void operator++() { stat.data(index)->inc(1); }
864 /**
865 * Decrement the stat by 1. This calls the associated storage object dec
866 * function.
867 */
868 void operator--() { stat.data(index)->dec(1); }
869
870 /** Increment the stat by 1. */
871 void operator++(int) { ++*this; }
872 /** Decrement the stat by 1. */
873 void operator--(int) { --*this; }
874
875 /**
876 * Set the data value to the given value. This calls the associated storage
877 * object set function.
878 * @param v The new value.
879 */
880 template <typename U>
881 void
882 operator=(const U &v)
883 {
884 stat.data(index)->set(v);
885 }
886
887 /**
888 * Increment the stat by the given value. This calls the associated
889 * storage object inc function.
890 * @param v The value to add.
891 */
892 template <typename U>
893 void
894 operator+=(const U &v)
895 {
896 stat.data(index)->inc(v);
897 }
898
899 /**
900 * Decrement the stat by the given value. This calls the associated
901 * storage object dec function.
902 * @param v The value to substract.
903 */
904 template <typename U>
905 void
906 operator-=(const U &v)
907 {
908 stat.data(index)->dec(v);
909 }
910
911 /**
912 * Return the number of elements, always 1 for a scalar.
913 * @return 1.
914 */
915 size_type size() const { return 1; }
916
917 public:
918 std::string
919 str() const
920 {
921 return csprintf("%s[%d]", stat.info()->name, index);
922 }
923};
924
925/**
926 * Implementation of a vector of stats. The type of stat is determined by the
927 * Storage class. @sa ScalarBase
928 */
929template <class Derived, class Stor>
930class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
931{
932 public:
933 typedef Stor Storage;
934 typedef typename Stor::Params Params;
935
936 /** Proxy type */
937 typedef ScalarProxy<Derived> Proxy;
938 friend class ScalarProxy<Derived>;
939 friend class DataWrapVec<Derived, VectorInfoProxy>;
940
941 protected:
942 /** The storage of this stat. */
943 Storage *storage;
944 size_type _size;
945
946 protected:
947 /**
948 * Retrieve the storage.
949 * @param index The vector index to access.
950 * @return The storage object at the given index.
951 */
952 Storage *data(off_type index) { return &storage[index]; }
953
954 /**
955 * Retrieve a const pointer to the storage.
956 * @param index The vector index to access.
957 * @return A const pointer to the storage object at the given index.
958 */
959 const Storage *data(off_type index) const { return &storage[index]; }
960
961 void
962 doInit(size_type s)
963 {
964 assert(s > 0 && "size must be positive!");
965 assert(!storage && "already initialized");
966 _size = s;
967
968 char *ptr = new char[_size * sizeof(Storage)];
969 storage = reinterpret_cast<Storage *>(ptr);
970
971 for (off_type i = 0; i < _size; ++i)
972 new (&storage[i]) Storage(this->info());
973
974 this->setInit();
975 }
976
977 public:
978 void
979 value(VCounter &vec) const
980 {
981 vec.resize(size());
982 for (off_type i = 0; i < size(); ++i)
983 vec[i] = data(i)->value();
984 }
985
986 /**
987 * Copy the values to a local vector and return a reference to it.
988 * @return A reference to a vector of the stat values.
989 */
990 void
991 result(VResult &vec) const
992 {
993 vec.resize(size());
994 for (off_type i = 0; i < size(); ++i)
995 vec[i] = data(i)->result();
996 }
997
998 /**
999 * Return a total of all entries in this vector.
1000 * @return The total of all vector entries.
1001 */
1002 Result
1003 total() const
1004 {
1005 Result total = 0.0;
1006 for (off_type i = 0; i < size(); ++i)
1007 total += data(i)->result();
1008 return total;
1009 }
1010
1011 /**
1012 * @return the number of elements in this vector.
1013 */
1014 size_type size() const { return _size; }
1015
1016 bool
1017 zero() const
1018 {
1019 for (off_type i = 0; i < size(); ++i)
1020 if (data(i)->zero())
1021 return false;
1022 return true;
1023 }
1024
1025 bool
1026 check() const
1027 {
1028 return storage != NULL;
1029 }
1030
1031 public:
1032 VectorBase()
1033 : storage(NULL)
1034 {}
1035
1036 ~VectorBase()
1037 {
1038 if (!storage)
1039 return;
1040
1041 for (off_type i = 0; i < _size; ++i)
1042 data(i)->~Storage();
1043 delete [] reinterpret_cast<char *>(storage);
1044 }
1045
1046 /**
1047 * Set this vector to have the given size.
1048 * @param size The new size.
1049 * @return A reference to this stat.
1050 */
1051 Derived &
1052 init(size_type size)
1053 {
1054 Derived &self = this->self();
1055 self.doInit(size);
1056 return self;
1057 }
1058
1059 /**
1060 * Return a reference (ScalarProxy) to the stat at the given index.
1061 * @param index The vector index to access.
1062 * @return A reference of the stat.
1063 */
1064 Proxy
1065 operator[](off_type index)
1066 {
1067 assert (index >= 0 && index < size());
1068 return Proxy(this->self(), index);
1069 }
1070};
1071
1072template <class Stat>
1073class VectorProxy
1074{
1075 private:
1076 Stat &stat;
1077 off_type offset;
1078 size_type len;
1079
1080 private:
1081 mutable VResult vec;
1082
1083 typename Stat::Storage *
1084 data(off_type index)
1085 {
1086 assert(index < len);
1087 return stat.data(offset + index);
1088 }
1089
1090 const typename Stat::Storage *
1091 data(off_type index) const
1092 {
1093 assert(index < len);
1094 return stat.data(offset + index);
1095 }
1096
1097 public:
1098 const VResult &
1099 result() const
1100 {
1101 vec.resize(size());
1102
1103 for (off_type i = 0; i < size(); ++i)
1104 vec[i] = data(i)->result();
1105
1106 return vec;
1107 }
1108
1109 Result
1110 total() const
1111 {
1112 Result total = 0.0;
1113 for (off_type i = 0; i < size(); ++i)
1114 total += data(i)->result();
1115 return total;
1116 }
1117
1118 public:
1119 VectorProxy(Stat &s, off_type o, size_type l)
1120 : stat(s), offset(o), len(l)
1121 {
1122 }
1123
1124 VectorProxy(const VectorProxy &sp)
1125 : stat(sp.stat), offset(sp.offset), len(sp.len)
1126 {
1127 }
1128
1129 const VectorProxy &
1130 operator=(const VectorProxy &sp)
1131 {
1132 stat = sp.stat;
1133 offset = sp.offset;
1134 len = sp.len;
1135 return *this;
1136 }
1137
1138 ScalarProxy<Stat>
1139 operator[](off_type index)
1140 {
1141 assert (index >= 0 && index < size());
1142 return ScalarProxy<Stat>(stat, offset + index);
1143 }
1144
1145 size_type size() const { return len; }
1146};
1147
1148template <class Derived, class Stor>
1149class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1150{
1151 public:
1152 typedef Vector2dInfoProxy<Derived> Info;
1153 typedef Stor Storage;
1154 typedef typename Stor::Params Params;
1155 typedef VectorProxy<Derived> Proxy;
1156 friend class ScalarProxy<Derived>;
1157 friend class VectorProxy<Derived>;
1158 friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1159 friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1160
1161 protected:
1162 size_type x;
1163 size_type y;
1164 size_type _size;
1165 Storage *storage;
1166
1167 protected:
1168 Storage *data(off_type index) { return &storage[index]; }
1169 const Storage *data(off_type index) const { return &storage[index]; }
1170
1171 public:
1172 Vector2dBase()
1173 : storage(NULL)
1174 {}
1175
1176 ~Vector2dBase()
1177 {
1178 if (!storage)
1179 return;
1180
1181 for (off_type i = 0; i < _size; ++i)
1182 data(i)->~Storage();
1183 delete [] reinterpret_cast<char *>(storage);
1184 }
1185
1186 Derived &
1187 init(size_type _x, size_type _y)
1188 {
1189 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1190 assert(!storage && "already initialized");
1191
1192 Derived &self = this->self();
1193 Info *info = this->info();
1194
1195 x = _x;
1196 y = _y;
1197 info->x = _x;
1198 info->y = _y;
1199 _size = x * y;
1200
1201 char *ptr = new char[_size * sizeof(Storage)];
1202 storage = reinterpret_cast<Storage *>(ptr);
1203
1204 for (off_type i = 0; i < _size; ++i)
1205 new (&storage[i]) Storage(info);
1206
1207 this->setInit();
1208
1209 return self;
1210 }
1211
1212 Proxy
1213 operator[](off_type index)
1214 {
1215 off_type offset = index * y;
1216 assert (index >= 0 && offset + index < size());
1217 return Proxy(this->self(), offset, y);
1218 }
1219
1220
1221 size_type
1222 size() const
1223 {
1224 return _size;
1225 }
1226
1227 bool
1228 zero() const
1229 {
1230 return data(0)->zero();
1231#if 0
1232 for (off_type i = 0; i < size(); ++i)
1233 if (!data(i)->zero())
1234 return false;
1235 return true;
1236#endif
1237 }
1238
1239 void
1240 prepare()
1241 {
1242 Info *info = this->info();
1243 size_type size = this->size();
1244
1245 for (off_type i = 0; i < size; ++i)
1246 data(i)->prepare(info);
1247
1248 info->cvec.resize(size);
1249 for (off_type i = 0; i < size; ++i)
1250 info->cvec[i] = data(i)->value();
1251 }
1252
1253 /**
1254 * Reset stat value to default
1255 */
1256 void
1257 reset()
1258 {
1259 Info *info = this->info();
1260 size_type size = this->size();
1261 for (off_type i = 0; i < size; ++i)
1262 data(i)->reset(info);
1263 }
1264
1265 bool
1266 check() const
1267 {
1268 return storage != NULL;
1269 }
1270};
1271
1272//////////////////////////////////////////////////////////////////////
1273//
1274// Non formula statistics
1275//
1276//////////////////////////////////////////////////////////////////////
1277/** The parameters for a distribution stat. */
1278struct DistParams : public StorageParams
1279{
1280 const DistType type;
1281 DistParams(DistType t) : type(t) {}
1282};
1283
1284/**
1285 * Templatized storage and interface for a distrbution stat.
1286 */
1287class DistStor
1288{
1289 public:
1290 /** The parameters for a distribution stat. */
1291 struct Params : public DistParams
1292 {
1293 /** The minimum value to track. */
1294 Counter min;
1295 /** The maximum value to track. */
1296 Counter max;
1297 /** The number of entries in each bucket. */
1298 Counter bucket_size;
1299 /** The number of buckets. Equal to (max-min)/bucket_size. */
1300 size_type buckets;
1301
1302 Params() : DistParams(Dist) {}
1303 };
1304
1305 private:
1306 /** The minimum value to track. */
1307 Counter min_track;
1308 /** The maximum value to track. */
1309 Counter max_track;
1310 /** The number of entries in each bucket. */
1311 Counter bucket_size;
1312 /** The number of buckets. Equal to (max-min)/bucket_size. */
1313 size_type buckets;
1314
1315 /** The smallest value sampled. */
1316 Counter min_val;
1317 /** The largest value sampled. */
1318 Counter max_val;
1319 /** The number of values sampled less than min. */
1320 Counter underflow;
1321 /** The number of values sampled more than max. */
1322 Counter overflow;
1323 /** The current sum. */
1324 Counter sum;
1325 /** The sum of squares. */
1326 Counter squares;
1327 /** The number of samples. */
1328 Counter samples;
1329 /** Counter for each bucket. */
1330 VCounter cvec;
1331
1332 public:
1333 DistStor(Info *info)
1334 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1335 {
1336 reset(info);
1337 }
1338
1339 /**
1340 * Add a value to the distribution for the given number of times.
1341 * @param val The value to add.
1342 * @param number The number of times to add the value.
1343 */
1344 void
1345 sample(Counter val, int number)
1346 {
1347 if (val < min_track)
1348 underflow += number;
1349 else if (val > max_track)
1350 overflow += number;
1351 else {
1352 size_type index =
1353 (size_type)std::floor((val - min_track) / bucket_size);
1354 assert(index < size());
1355 cvec[index] += number;
1356 }
1357
1358 if (val < min_val)
1359 min_val = val;
1360
1361 if (val > max_val)
1362 max_val = val;
1363
1364 Counter sample = val * number;
1365 sum += sample;
1366 squares += sample * sample;
1367 samples += number;
1368 }
1369
1370 /**
1371 * Return the number of buckets in this distribution.
1372 * @return the number of buckets.
1373 */
1374 size_type size() const { return cvec.size(); }
1375
1376 /**
1377 * Returns true if any calls to sample have been made.
1378 * @return True if any values have been sampled.
1379 */
1380 bool
1381 zero() const
1382 {
1383 return samples == Counter();
1384 }
1385
1386 void
1387 prepare(Info *info, DistData &data)
1388 {
1389 const Params *params = safe_cast<const Params *>(info->storageParams);
1390
1391 assert(params->type == Dist);
1392 data.type = params->type;
1393 data.min = params->min;
1394 data.max = params->max;
1395 data.bucket_size = params->bucket_size;
1396
1397 data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1398 data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1399 data.underflow = underflow;
1400 data.overflow = overflow;
1401
1402 size_type buckets = params->buckets;
1403 data.cvec.resize(buckets);
1404 for (off_type i = 0; i < buckets; ++i)
1405 data.cvec[i] = cvec[i];
1406
1407 data.sum = sum;
1408 data.squares = squares;
1409 data.samples = samples;
1410 }
1411
1412 /**
1413 * Reset stat value to default
1414 */
1415 void
1416 reset(Info *info)
1417 {
1418 const Params *params = safe_cast<const Params *>(info->storageParams);
1419 min_track = params->min;
1420 max_track = params->max;
1421 bucket_size = params->bucket_size;
1422
1423 min_val = CounterLimits::max();
1424 max_val = CounterLimits::min();
1425 underflow = Counter();
1426 overflow = Counter();
1427
1428 size_type size = cvec.size();
1429 for (off_type i = 0; i < size; ++i)
1430 cvec[i] = Counter();
1431
1432 sum = Counter();
1433 squares = Counter();
1434 samples = Counter();
1435 }
1436};
1437
1438/**
1439 * Templatized storage and interface for a distribution that calculates mean
1440 * and variance.
1441 */
1442class SampleStor
1443{
1444 public:
1445 struct Params : public DistParams
1446 {
1447 Params() : DistParams(Deviation) {}
1448 };
1449
1450 private:
1451 /** The current sum. */
1452 Counter sum;
1453 /** The sum of squares. */
1454 Counter squares;
1455 /** The number of samples. */
1456 Counter samples;
1457
1458 public:
1459 /**
1460 * Create and initialize this storage.
1461 */
1462 SampleStor(Info *info)
1463 : sum(Counter()), squares(Counter()), samples(Counter())
1464 { }
1465
1466 /**
1467 * Add a value the given number of times to this running average.
1468 * Update the running sum and sum of squares, increment the number of
1469 * values seen by the given number.
1470 * @param val The value to add.
1471 * @param number The number of times to add the value.
1472 */
1473 void
1474 sample(Counter val, int number)
1475 {
1476 Counter value = val * number;
1477 sum += value;
1478 squares += value * value;
1479 samples += number;
1480 }
1481
1482 /**
1483 * Return the number of entries in this stat, 1
1484 * @return 1.
1485 */
1486 size_type size() const { return 1; }
1487
1488 /**
1489 * Return true if no samples have been added.
1490 * @return True if no samples have been added.
1491 */
1492 bool zero() const { return samples == Counter(); }
1493
1494 void
1495 prepare(Info *info, DistData &data)
1496 {
1497 const Params *params = safe_cast<const Params *>(info->storageParams);
1498
1499 assert(params->type == Deviation);
1500 data.type = params->type;
1501 data.sum = sum;
1502 data.squares = squares;
1503 data.samples = samples;
1504 }
1505
1506 /**
1507 * Reset stat value to default
1508 */
1509 void
1510 reset(Info *info)
1511 {
1512 sum = Counter();
1513 squares = Counter();
1514 samples = Counter();
1515 }
1516};
1517
1518/**
1519 * Templatized storage for distribution that calculates per tick mean and
1520 * variance.
1521 */
1522class AvgSampleStor
1523{
1524 public:
1525 struct Params : public DistParams
1526 {
1527 Params() : DistParams(Deviation) {}
1528 };
1529
1530 private:
1531 /** Current total. */
1532 Counter sum;
1533 /** Current sum of squares. */
1534 Counter squares;
1535
1536 public:
1537 /**
1538 * Create and initialize this storage.
1539 */
1540 AvgSampleStor(Info *info)
1541 : sum(Counter()), squares(Counter())
1542 {}
1543
1544 /**
1545 * Add a value to the distribution for the given number of times.
1546 * Update the running sum and sum of squares.
1547 * @param val The value to add.
1548 * @param number The number of times to add the value.
1549 */
1550 void
1551 sample(Counter val, int number)
1552 {
1553 Counter value = val * number;
1554 sum += value;
1555 squares += value * value;
1556 }
1557
1558 /**
1559 * Return the number of entries, in this case 1.
1560 * @return 1.
1561 */
1562 size_type size() const { return 1; }
1563
1564 /**
1565 * Return true if no samples have been added.
1566 * @return True if the sum is zero.
1567 */
1568 bool zero() const { return sum == Counter(); }
1569
1570 void
1571 prepare(Info *info, DistData &data)
1572 {
1573 const Params *params = safe_cast<const Params *>(info->storageParams);
1574
1575 assert(params->type == Deviation);
1576 data.type = params->type;
1577 data.sum = sum;
1578 data.squares = squares;
591 }
592
593};
594
595/**
596 * Implementation of a scalar stat. The type of stat is determined by the
597 * Storage template.
598 */
599template <class Derived, class Stor>
600class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
601{
602 public:
603 typedef Stor Storage;
604 typedef typename Stor::Params Params;
605
606 protected:
607 /** The storage of this stat. */
608 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
609
610 protected:
611 /**
612 * Retrieve the storage.
613 * @param index The vector index to access.
614 * @return The storage object at the given index.
615 */
616 Storage *
617 data()
618 {
619 return reinterpret_cast<Storage *>(storage);
620 }
621
622 /**
623 * Retrieve a const pointer to the storage.
624 * for the given index.
625 * @param index The vector index to access.
626 * @return A const pointer to the storage object at the given index.
627 */
628 const Storage *
629 data() const
630 {
631 return reinterpret_cast<const Storage *>(storage);
632 }
633
634 void
635 doInit()
636 {
637 new (storage) Storage(this->info());
638 this->setInit();
639 }
640
641 public:
642 /**
643 * Return the current value of this stat as its base type.
644 * @return The current value.
645 */
646 Counter value() const { return data()->value(); }
647
648 public:
649 ScalarBase()
650 {
651 this->doInit();
652 }
653
654 public:
655 // Common operators for stats
656 /**
657 * Increment the stat by 1. This calls the associated storage object inc
658 * function.
659 */
660 void operator++() { data()->inc(1); }
661 /**
662 * Decrement the stat by 1. This calls the associated storage object dec
663 * function.
664 */
665 void operator--() { data()->dec(1); }
666
667 /** Increment the stat by 1. */
668 void operator++(int) { ++*this; }
669 /** Decrement the stat by 1. */
670 void operator--(int) { --*this; }
671
672 /**
673 * Set the data value to the given value. This calls the associated storage
674 * object set function.
675 * @param v The new value.
676 */
677 template <typename U>
678 void operator=(const U &v) { data()->set(v); }
679
680 /**
681 * Increment the stat by the given value. This calls the associated
682 * storage object inc function.
683 * @param v The value to add.
684 */
685 template <typename U>
686 void operator+=(const U &v) { data()->inc(v); }
687
688 /**
689 * Decrement the stat by the given value. This calls the associated
690 * storage object dec function.
691 * @param v The value to substract.
692 */
693 template <typename U>
694 void operator-=(const U &v) { data()->dec(v); }
695
696 /**
697 * Return the number of elements, always 1 for a scalar.
698 * @return 1.
699 */
700 size_type size() const { return 1; }
701
702 Counter value() { return data()->value(); }
703
704 Result result() { return data()->result(); }
705
706 Result total() { return result(); }
707
708 bool zero() { return result() == 0.0; }
709
710 void reset() { data()->reset(this->info()); }
711 void prepare() { data()->prepare(this->info()); }
712};
713
714class ProxyInfo : public ScalarInfo
715{
716 public:
717 std::string str() const { return to_string(value()); }
718 size_type size() const { return 1; }
719 bool check() const { return true; }
720 void prepare() { }
721 void reset() { }
722 bool zero() const { return value() == 0; }
723
724 void visit(Visit &visitor) { visitor.visit(*this); }
725};
726
727template <class T>
728class ValueProxy : public ProxyInfo
729{
730 private:
731 T *scalar;
732
733 public:
734 ValueProxy(T &val) : scalar(&val) {}
735 Counter value() const { return *scalar; }
736 Result result() const { return *scalar; }
737 Result total() const { return *scalar; }
738};
739
740template <class T>
741class FunctorProxy : public ProxyInfo
742{
743 private:
744 T *functor;
745
746 public:
747 FunctorProxy(T &func) : functor(&func) {}
748 Counter value() const { return (*functor)(); }
749 Result result() const { return (*functor)(); }
750 Result total() const { return (*functor)(); }
751};
752
753template <class Derived>
754class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
755{
756 private:
757 ProxyInfo *proxy;
758
759 public:
760 ValueBase() : proxy(NULL) { }
761 ~ValueBase() { if (proxy) delete proxy; }
762
763 template <class T>
764 Derived &
765 scalar(T &value)
766 {
767 proxy = new ValueProxy<T>(value);
768 this->setInit();
769 return this->self();
770 }
771
772 template <class T>
773 Derived &
774 functor(T &func)
775 {
776 proxy = new FunctorProxy<T>(func);
777 this->setInit();
778 return this->self();
779 }
780
781 Counter value() { return proxy->value(); }
782 Result result() const { return proxy->result(); }
783 Result total() const { return proxy->total(); };
784 size_type size() const { return proxy->size(); }
785
786 std::string str() const { return proxy->str(); }
787 bool zero() const { return proxy->zero(); }
788 bool check() const { return proxy != NULL; }
789 void prepare() { }
790 void reset() { }
791};
792
793//////////////////////////////////////////////////////////////////////
794//
795// Vector Statistics
796//
797//////////////////////////////////////////////////////////////////////
798
799/**
800 * A proxy class to access the stat at a given index in a VectorBase stat.
801 * Behaves like a ScalarBase.
802 */
803template <class Stat>
804class ScalarProxy
805{
806 private:
807 /** Pointer to the parent Vector. */
808 Stat &stat;
809
810 /** The index to access in the parent VectorBase. */
811 off_type index;
812
813 public:
814 /**
815 * Return the current value of this stat as its base type.
816 * @return The current value.
817 */
818 Counter value() const { return stat.data(index)->value(); }
819
820 /**
821 * Return the current value of this statas a result type.
822 * @return The current value.
823 */
824 Result result() const { return stat.data(index)->result(); }
825
826 public:
827 /**
828 * Create and initialize this proxy, do not register it with the database.
829 * @param i The index to access.
830 */
831 ScalarProxy(Stat &s, off_type i)
832 : stat(s), index(i)
833 {
834 }
835
836 /**
837 * Create a copy of the provided ScalarProxy.
838 * @param sp The proxy to copy.
839 */
840 ScalarProxy(const ScalarProxy &sp)
841 : stat(sp.stat), index(sp.index)
842 {}
843
844 /**
845 * Set this proxy equal to the provided one.
846 * @param sp The proxy to copy.
847 * @return A reference to this proxy.
848 */
849 const ScalarProxy &
850 operator=(const ScalarProxy &sp)
851 {
852 stat = sp.stat;
853 index = sp.index;
854 return *this;
855 }
856
857 public:
858 // Common operators for stats
859 /**
860 * Increment the stat by 1. This calls the associated storage object inc
861 * function.
862 */
863 void operator++() { stat.data(index)->inc(1); }
864 /**
865 * Decrement the stat by 1. This calls the associated storage object dec
866 * function.
867 */
868 void operator--() { stat.data(index)->dec(1); }
869
870 /** Increment the stat by 1. */
871 void operator++(int) { ++*this; }
872 /** Decrement the stat by 1. */
873 void operator--(int) { --*this; }
874
875 /**
876 * Set the data value to the given value. This calls the associated storage
877 * object set function.
878 * @param v The new value.
879 */
880 template <typename U>
881 void
882 operator=(const U &v)
883 {
884 stat.data(index)->set(v);
885 }
886
887 /**
888 * Increment the stat by the given value. This calls the associated
889 * storage object inc function.
890 * @param v The value to add.
891 */
892 template <typename U>
893 void
894 operator+=(const U &v)
895 {
896 stat.data(index)->inc(v);
897 }
898
899 /**
900 * Decrement the stat by the given value. This calls the associated
901 * storage object dec function.
902 * @param v The value to substract.
903 */
904 template <typename U>
905 void
906 operator-=(const U &v)
907 {
908 stat.data(index)->dec(v);
909 }
910
911 /**
912 * Return the number of elements, always 1 for a scalar.
913 * @return 1.
914 */
915 size_type size() const { return 1; }
916
917 public:
918 std::string
919 str() const
920 {
921 return csprintf("%s[%d]", stat.info()->name, index);
922 }
923};
924
925/**
926 * Implementation of a vector of stats. The type of stat is determined by the
927 * Storage class. @sa ScalarBase
928 */
929template <class Derived, class Stor>
930class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
931{
932 public:
933 typedef Stor Storage;
934 typedef typename Stor::Params Params;
935
936 /** Proxy type */
937 typedef ScalarProxy<Derived> Proxy;
938 friend class ScalarProxy<Derived>;
939 friend class DataWrapVec<Derived, VectorInfoProxy>;
940
941 protected:
942 /** The storage of this stat. */
943 Storage *storage;
944 size_type _size;
945
946 protected:
947 /**
948 * Retrieve the storage.
949 * @param index The vector index to access.
950 * @return The storage object at the given index.
951 */
952 Storage *data(off_type index) { return &storage[index]; }
953
954 /**
955 * Retrieve a const pointer to the storage.
956 * @param index The vector index to access.
957 * @return A const pointer to the storage object at the given index.
958 */
959 const Storage *data(off_type index) const { return &storage[index]; }
960
961 void
962 doInit(size_type s)
963 {
964 assert(s > 0 && "size must be positive!");
965 assert(!storage && "already initialized");
966 _size = s;
967
968 char *ptr = new char[_size * sizeof(Storage)];
969 storage = reinterpret_cast<Storage *>(ptr);
970
971 for (off_type i = 0; i < _size; ++i)
972 new (&storage[i]) Storage(this->info());
973
974 this->setInit();
975 }
976
977 public:
978 void
979 value(VCounter &vec) const
980 {
981 vec.resize(size());
982 for (off_type i = 0; i < size(); ++i)
983 vec[i] = data(i)->value();
984 }
985
986 /**
987 * Copy the values to a local vector and return a reference to it.
988 * @return A reference to a vector of the stat values.
989 */
990 void
991 result(VResult &vec) const
992 {
993 vec.resize(size());
994 for (off_type i = 0; i < size(); ++i)
995 vec[i] = data(i)->result();
996 }
997
998 /**
999 * Return a total of all entries in this vector.
1000 * @return The total of all vector entries.
1001 */
1002 Result
1003 total() const
1004 {
1005 Result total = 0.0;
1006 for (off_type i = 0; i < size(); ++i)
1007 total += data(i)->result();
1008 return total;
1009 }
1010
1011 /**
1012 * @return the number of elements in this vector.
1013 */
1014 size_type size() const { return _size; }
1015
1016 bool
1017 zero() const
1018 {
1019 for (off_type i = 0; i < size(); ++i)
1020 if (data(i)->zero())
1021 return false;
1022 return true;
1023 }
1024
1025 bool
1026 check() const
1027 {
1028 return storage != NULL;
1029 }
1030
1031 public:
1032 VectorBase()
1033 : storage(NULL)
1034 {}
1035
1036 ~VectorBase()
1037 {
1038 if (!storage)
1039 return;
1040
1041 for (off_type i = 0; i < _size; ++i)
1042 data(i)->~Storage();
1043 delete [] reinterpret_cast<char *>(storage);
1044 }
1045
1046 /**
1047 * Set this vector to have the given size.
1048 * @param size The new size.
1049 * @return A reference to this stat.
1050 */
1051 Derived &
1052 init(size_type size)
1053 {
1054 Derived &self = this->self();
1055 self.doInit(size);
1056 return self;
1057 }
1058
1059 /**
1060 * Return a reference (ScalarProxy) to the stat at the given index.
1061 * @param index The vector index to access.
1062 * @return A reference of the stat.
1063 */
1064 Proxy
1065 operator[](off_type index)
1066 {
1067 assert (index >= 0 && index < size());
1068 return Proxy(this->self(), index);
1069 }
1070};
1071
1072template <class Stat>
1073class VectorProxy
1074{
1075 private:
1076 Stat &stat;
1077 off_type offset;
1078 size_type len;
1079
1080 private:
1081 mutable VResult vec;
1082
1083 typename Stat::Storage *
1084 data(off_type index)
1085 {
1086 assert(index < len);
1087 return stat.data(offset + index);
1088 }
1089
1090 const typename Stat::Storage *
1091 data(off_type index) const
1092 {
1093 assert(index < len);
1094 return stat.data(offset + index);
1095 }
1096
1097 public:
1098 const VResult &
1099 result() const
1100 {
1101 vec.resize(size());
1102
1103 for (off_type i = 0; i < size(); ++i)
1104 vec[i] = data(i)->result();
1105
1106 return vec;
1107 }
1108
1109 Result
1110 total() const
1111 {
1112 Result total = 0.0;
1113 for (off_type i = 0; i < size(); ++i)
1114 total += data(i)->result();
1115 return total;
1116 }
1117
1118 public:
1119 VectorProxy(Stat &s, off_type o, size_type l)
1120 : stat(s), offset(o), len(l)
1121 {
1122 }
1123
1124 VectorProxy(const VectorProxy &sp)
1125 : stat(sp.stat), offset(sp.offset), len(sp.len)
1126 {
1127 }
1128
1129 const VectorProxy &
1130 operator=(const VectorProxy &sp)
1131 {
1132 stat = sp.stat;
1133 offset = sp.offset;
1134 len = sp.len;
1135 return *this;
1136 }
1137
1138 ScalarProxy<Stat>
1139 operator[](off_type index)
1140 {
1141 assert (index >= 0 && index < size());
1142 return ScalarProxy<Stat>(stat, offset + index);
1143 }
1144
1145 size_type size() const { return len; }
1146};
1147
1148template <class Derived, class Stor>
1149class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1150{
1151 public:
1152 typedef Vector2dInfoProxy<Derived> Info;
1153 typedef Stor Storage;
1154 typedef typename Stor::Params Params;
1155 typedef VectorProxy<Derived> Proxy;
1156 friend class ScalarProxy<Derived>;
1157 friend class VectorProxy<Derived>;
1158 friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1159 friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1160
1161 protected:
1162 size_type x;
1163 size_type y;
1164 size_type _size;
1165 Storage *storage;
1166
1167 protected:
1168 Storage *data(off_type index) { return &storage[index]; }
1169 const Storage *data(off_type index) const { return &storage[index]; }
1170
1171 public:
1172 Vector2dBase()
1173 : storage(NULL)
1174 {}
1175
1176 ~Vector2dBase()
1177 {
1178 if (!storage)
1179 return;
1180
1181 for (off_type i = 0; i < _size; ++i)
1182 data(i)->~Storage();
1183 delete [] reinterpret_cast<char *>(storage);
1184 }
1185
1186 Derived &
1187 init(size_type _x, size_type _y)
1188 {
1189 assert(_x > 0 && _y > 0 && "sizes must be positive!");
1190 assert(!storage && "already initialized");
1191
1192 Derived &self = this->self();
1193 Info *info = this->info();
1194
1195 x = _x;
1196 y = _y;
1197 info->x = _x;
1198 info->y = _y;
1199 _size = x * y;
1200
1201 char *ptr = new char[_size * sizeof(Storage)];
1202 storage = reinterpret_cast<Storage *>(ptr);
1203
1204 for (off_type i = 0; i < _size; ++i)
1205 new (&storage[i]) Storage(info);
1206
1207 this->setInit();
1208
1209 return self;
1210 }
1211
1212 Proxy
1213 operator[](off_type index)
1214 {
1215 off_type offset = index * y;
1216 assert (index >= 0 && offset + index < size());
1217 return Proxy(this->self(), offset, y);
1218 }
1219
1220
1221 size_type
1222 size() const
1223 {
1224 return _size;
1225 }
1226
1227 bool
1228 zero() const
1229 {
1230 return data(0)->zero();
1231#if 0
1232 for (off_type i = 0; i < size(); ++i)
1233 if (!data(i)->zero())
1234 return false;
1235 return true;
1236#endif
1237 }
1238
1239 void
1240 prepare()
1241 {
1242 Info *info = this->info();
1243 size_type size = this->size();
1244
1245 for (off_type i = 0; i < size; ++i)
1246 data(i)->prepare(info);
1247
1248 info->cvec.resize(size);
1249 for (off_type i = 0; i < size; ++i)
1250 info->cvec[i] = data(i)->value();
1251 }
1252
1253 /**
1254 * Reset stat value to default
1255 */
1256 void
1257 reset()
1258 {
1259 Info *info = this->info();
1260 size_type size = this->size();
1261 for (off_type i = 0; i < size; ++i)
1262 data(i)->reset(info);
1263 }
1264
1265 bool
1266 check() const
1267 {
1268 return storage != NULL;
1269 }
1270};
1271
1272//////////////////////////////////////////////////////////////////////
1273//
1274// Non formula statistics
1275//
1276//////////////////////////////////////////////////////////////////////
1277/** The parameters for a distribution stat. */
1278struct DistParams : public StorageParams
1279{
1280 const DistType type;
1281 DistParams(DistType t) : type(t) {}
1282};
1283
1284/**
1285 * Templatized storage and interface for a distrbution stat.
1286 */
1287class DistStor
1288{
1289 public:
1290 /** The parameters for a distribution stat. */
1291 struct Params : public DistParams
1292 {
1293 /** The minimum value to track. */
1294 Counter min;
1295 /** The maximum value to track. */
1296 Counter max;
1297 /** The number of entries in each bucket. */
1298 Counter bucket_size;
1299 /** The number of buckets. Equal to (max-min)/bucket_size. */
1300 size_type buckets;
1301
1302 Params() : DistParams(Dist) {}
1303 };
1304
1305 private:
1306 /** The minimum value to track. */
1307 Counter min_track;
1308 /** The maximum value to track. */
1309 Counter max_track;
1310 /** The number of entries in each bucket. */
1311 Counter bucket_size;
1312 /** The number of buckets. Equal to (max-min)/bucket_size. */
1313 size_type buckets;
1314
1315 /** The smallest value sampled. */
1316 Counter min_val;
1317 /** The largest value sampled. */
1318 Counter max_val;
1319 /** The number of values sampled less than min. */
1320 Counter underflow;
1321 /** The number of values sampled more than max. */
1322 Counter overflow;
1323 /** The current sum. */
1324 Counter sum;
1325 /** The sum of squares. */
1326 Counter squares;
1327 /** The number of samples. */
1328 Counter samples;
1329 /** Counter for each bucket. */
1330 VCounter cvec;
1331
1332 public:
1333 DistStor(Info *info)
1334 : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1335 {
1336 reset(info);
1337 }
1338
1339 /**
1340 * Add a value to the distribution for the given number of times.
1341 * @param val The value to add.
1342 * @param number The number of times to add the value.
1343 */
1344 void
1345 sample(Counter val, int number)
1346 {
1347 if (val < min_track)
1348 underflow += number;
1349 else if (val > max_track)
1350 overflow += number;
1351 else {
1352 size_type index =
1353 (size_type)std::floor((val - min_track) / bucket_size);
1354 assert(index < size());
1355 cvec[index] += number;
1356 }
1357
1358 if (val < min_val)
1359 min_val = val;
1360
1361 if (val > max_val)
1362 max_val = val;
1363
1364 Counter sample = val * number;
1365 sum += sample;
1366 squares += sample * sample;
1367 samples += number;
1368 }
1369
1370 /**
1371 * Return the number of buckets in this distribution.
1372 * @return the number of buckets.
1373 */
1374 size_type size() const { return cvec.size(); }
1375
1376 /**
1377 * Returns true if any calls to sample have been made.
1378 * @return True if any values have been sampled.
1379 */
1380 bool
1381 zero() const
1382 {
1383 return samples == Counter();
1384 }
1385
1386 void
1387 prepare(Info *info, DistData &data)
1388 {
1389 const Params *params = safe_cast<const Params *>(info->storageParams);
1390
1391 assert(params->type == Dist);
1392 data.type = params->type;
1393 data.min = params->min;
1394 data.max = params->max;
1395 data.bucket_size = params->bucket_size;
1396
1397 data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1398 data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1399 data.underflow = underflow;
1400 data.overflow = overflow;
1401
1402 size_type buckets = params->buckets;
1403 data.cvec.resize(buckets);
1404 for (off_type i = 0; i < buckets; ++i)
1405 data.cvec[i] = cvec[i];
1406
1407 data.sum = sum;
1408 data.squares = squares;
1409 data.samples = samples;
1410 }
1411
1412 /**
1413 * Reset stat value to default
1414 */
1415 void
1416 reset(Info *info)
1417 {
1418 const Params *params = safe_cast<const Params *>(info->storageParams);
1419 min_track = params->min;
1420 max_track = params->max;
1421 bucket_size = params->bucket_size;
1422
1423 min_val = CounterLimits::max();
1424 max_val = CounterLimits::min();
1425 underflow = Counter();
1426 overflow = Counter();
1427
1428 size_type size = cvec.size();
1429 for (off_type i = 0; i < size; ++i)
1430 cvec[i] = Counter();
1431
1432 sum = Counter();
1433 squares = Counter();
1434 samples = Counter();
1435 }
1436};
1437
1438/**
1439 * Templatized storage and interface for a distribution that calculates mean
1440 * and variance.
1441 */
1442class SampleStor
1443{
1444 public:
1445 struct Params : public DistParams
1446 {
1447 Params() : DistParams(Deviation) {}
1448 };
1449
1450 private:
1451 /** The current sum. */
1452 Counter sum;
1453 /** The sum of squares. */
1454 Counter squares;
1455 /** The number of samples. */
1456 Counter samples;
1457
1458 public:
1459 /**
1460 * Create and initialize this storage.
1461 */
1462 SampleStor(Info *info)
1463 : sum(Counter()), squares(Counter()), samples(Counter())
1464 { }
1465
1466 /**
1467 * Add a value the given number of times to this running average.
1468 * Update the running sum and sum of squares, increment the number of
1469 * values seen by the given number.
1470 * @param val The value to add.
1471 * @param number The number of times to add the value.
1472 */
1473 void
1474 sample(Counter val, int number)
1475 {
1476 Counter value = val * number;
1477 sum += value;
1478 squares += value * value;
1479 samples += number;
1480 }
1481
1482 /**
1483 * Return the number of entries in this stat, 1
1484 * @return 1.
1485 */
1486 size_type size() const { return 1; }
1487
1488 /**
1489 * Return true if no samples have been added.
1490 * @return True if no samples have been added.
1491 */
1492 bool zero() const { return samples == Counter(); }
1493
1494 void
1495 prepare(Info *info, DistData &data)
1496 {
1497 const Params *params = safe_cast<const Params *>(info->storageParams);
1498
1499 assert(params->type == Deviation);
1500 data.type = params->type;
1501 data.sum = sum;
1502 data.squares = squares;
1503 data.samples = samples;
1504 }
1505
1506 /**
1507 * Reset stat value to default
1508 */
1509 void
1510 reset(Info *info)
1511 {
1512 sum = Counter();
1513 squares = Counter();
1514 samples = Counter();
1515 }
1516};
1517
1518/**
1519 * Templatized storage for distribution that calculates per tick mean and
1520 * variance.
1521 */
1522class AvgSampleStor
1523{
1524 public:
1525 struct Params : public DistParams
1526 {
1527 Params() : DistParams(Deviation) {}
1528 };
1529
1530 private:
1531 /** Current total. */
1532 Counter sum;
1533 /** Current sum of squares. */
1534 Counter squares;
1535
1536 public:
1537 /**
1538 * Create and initialize this storage.
1539 */
1540 AvgSampleStor(Info *info)
1541 : sum(Counter()), squares(Counter())
1542 {}
1543
1544 /**
1545 * Add a value to the distribution for the given number of times.
1546 * Update the running sum and sum of squares.
1547 * @param val The value to add.
1548 * @param number The number of times to add the value.
1549 */
1550 void
1551 sample(Counter val, int number)
1552 {
1553 Counter value = val * number;
1554 sum += value;
1555 squares += value * value;
1556 }
1557
1558 /**
1559 * Return the number of entries, in this case 1.
1560 * @return 1.
1561 */
1562 size_type size() const { return 1; }
1563
1564 /**
1565 * Return true if no samples have been added.
1566 * @return True if the sum is zero.
1567 */
1568 bool zero() const { return sum == Counter(); }
1569
1570 void
1571 prepare(Info *info, DistData &data)
1572 {
1573 const Params *params = safe_cast<const Params *>(info->storageParams);
1574
1575 assert(params->type == Deviation);
1576 data.type = params->type;
1577 data.sum = sum;
1578 data.squares = squares;
1579 data.samples = curTick;
1579 data.samples = curTick();
1580 }
1581
1582 /**
1583 * Reset stat value to default
1584 */
1585 void
1586 reset(Info *info)
1587 {
1588 sum = Counter();
1589 squares = Counter();
1590 }
1591};
1592
1593/**
1594 * Implementation of a distribution stat. The type of distribution is
1595 * determined by the Storage template. @sa ScalarBase
1596 */
1597template <class Derived, class Stor>
1598class DistBase : public DataWrap<Derived, DistInfoProxy>
1599{
1600 public:
1601 typedef DistInfoProxy<Derived> Info;
1602 typedef Stor Storage;
1603 typedef typename Stor::Params Params;
1604
1605 protected:
1606 /** The storage for this stat. */
1607 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1608
1609 protected:
1610 /**
1611 * Retrieve the storage.
1612 * @return The storage object for this stat.
1613 */
1614 Storage *
1615 data()
1616 {
1617 return reinterpret_cast<Storage *>(storage);
1618 }
1619
1620 /**
1621 * Retrieve a const pointer to the storage.
1622 * @return A const pointer to the storage object for this stat.
1623 */
1624 const Storage *
1625 data() const
1626 {
1627 return reinterpret_cast<const Storage *>(storage);
1628 }
1629
1630 void
1631 doInit()
1632 {
1633 new (storage) Storage(this->info());
1634 this->setInit();
1635 }
1636
1637 public:
1638 DistBase() { }
1639
1640 /**
1641 * Add a value to the distribtion n times. Calls sample on the storage
1642 * class.
1643 * @param v The value to add.
1644 * @param n The number of times to add it, defaults to 1.
1645 */
1646 template <typename U>
1647 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1648
1649 /**
1650 * Return the number of entries in this stat.
1651 * @return The number of entries.
1652 */
1653 size_type size() const { return data()->size(); }
1654 /**
1655 * Return true if no samples have been added.
1656 * @return True if there haven't been any samples.
1657 */
1658 bool zero() const { return data()->zero(); }
1659
1660 void
1661 prepare()
1662 {
1663 Info *info = this->info();
1664 data()->prepare(info, info->data);
1665 }
1666
1667 /**
1668 * Reset stat value to default
1669 */
1670 void
1671 reset()
1672 {
1673 data()->reset(this->info());
1674 }
1675};
1676
1677template <class Stat>
1678class DistProxy;
1679
1680template <class Derived, class Stor>
1681class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1682{
1683 public:
1684 typedef VectorDistInfoProxy<Derived> Info;
1685 typedef Stor Storage;
1686 typedef typename Stor::Params Params;
1687 typedef DistProxy<Derived> Proxy;
1688 friend class DistProxy<Derived>;
1689 friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1690
1691 protected:
1692 Storage *storage;
1693 size_type _size;
1694
1695 protected:
1696 Storage *
1697 data(off_type index)
1698 {
1699 return &storage[index];
1700 }
1701
1702 const Storage *
1703 data(off_type index) const
1704 {
1705 return &storage[index];
1706 }
1707
1708 void
1709 doInit(size_type s)
1710 {
1711 assert(s > 0 && "size must be positive!");
1712 assert(!storage && "already initialized");
1713 _size = s;
1714
1715 char *ptr = new char[_size * sizeof(Storage)];
1716 storage = reinterpret_cast<Storage *>(ptr);
1717
1718 Info *info = this->info();
1719 for (off_type i = 0; i < _size; ++i)
1720 new (&storage[i]) Storage(info);
1721
1722 this->setInit();
1723 }
1724
1725 public:
1726 VectorDistBase()
1727 : storage(NULL)
1728 {}
1729
1730 ~VectorDistBase()
1731 {
1732 if (!storage)
1733 return ;
1734
1735 for (off_type i = 0; i < _size; ++i)
1736 data(i)->~Storage();
1737 delete [] reinterpret_cast<char *>(storage);
1738 }
1739
1740 Proxy operator[](off_type index)
1741 {
1742 assert(index >= 0 && index < size());
1743 return Proxy(this->self(), index);
1744 }
1745
1746 size_type
1747 size() const
1748 {
1749 return _size;
1750 }
1751
1752 bool
1753 zero() const
1754 {
1755 for (off_type i = 0; i < size(); ++i)
1756 if (!data(i)->zero())
1757 return false;
1758 return true;
1759 }
1760
1761 void
1762 prepare()
1763 {
1764 Info *info = this->info();
1765 size_type size = this->size();
1766 info->data.resize(size);
1767 for (off_type i = 0; i < size; ++i)
1768 data(i)->prepare(info, info->data[i]);
1769 }
1770
1771 bool
1772 check() const
1773 {
1774 return storage != NULL;
1775 }
1776};
1777
1778template <class Stat>
1779class DistProxy
1780{
1781 private:
1782 Stat &stat;
1783 off_type index;
1784
1785 protected:
1786 typename Stat::Storage *data() { return stat.data(index); }
1787 const typename Stat::Storage *data() const { return stat.data(index); }
1788
1789 public:
1790 DistProxy(Stat &s, off_type i)
1791 : stat(s), index(i)
1792 {}
1793
1794 DistProxy(const DistProxy &sp)
1795 : stat(sp.stat), index(sp.index)
1796 {}
1797
1798 const DistProxy &
1799 operator=(const DistProxy &sp)
1800 {
1801 stat = sp.stat;
1802 index = sp.index;
1803 return *this;
1804 }
1805
1806 public:
1807 template <typename U>
1808 void
1809 sample(const U &v, int n = 1)
1810 {
1811 data()->sample(v, n);
1812 }
1813
1814 size_type
1815 size() const
1816 {
1817 return 1;
1818 }
1819
1820 bool
1821 zero() const
1822 {
1823 return data()->zero();
1824 }
1825
1826 /**
1827 * Proxy has no state. Nothing to reset.
1828 */
1829 void reset() { }
1830};
1831
1832//////////////////////////////////////////////////////////////////////
1833//
1834// Formula Details
1835//
1836//////////////////////////////////////////////////////////////////////
1837
1838/**
1839 * Base class for formula statistic node. These nodes are used to build a tree
1840 * that represents the formula.
1841 */
1842class Node : public RefCounted
1843{
1844 public:
1845 /**
1846 * Return the number of nodes in the subtree starting at this node.
1847 * @return the number of nodes in this subtree.
1848 */
1849 virtual size_type size() const = 0;
1850 /**
1851 * Return the result vector of this subtree.
1852 * @return The result vector of this subtree.
1853 */
1854 virtual const VResult &result() const = 0;
1855 /**
1856 * Return the total of the result vector.
1857 * @return The total of the result vector.
1858 */
1859 virtual Result total() const = 0;
1860
1861 /**
1862 *
1863 */
1864 virtual std::string str() const = 0;
1865};
1866
1867/** Reference counting pointer to a function Node. */
1868typedef RefCountingPtr<Node> NodePtr;
1869
1870class ScalarStatNode : public Node
1871{
1872 private:
1873 const ScalarInfo *data;
1874 mutable VResult vresult;
1875
1876 public:
1877 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
1878
1879 const VResult &
1880 result() const
1881 {
1882 vresult[0] = data->result();
1883 return vresult;
1884 }
1885
1886 Result total() const { return data->result(); };
1887
1888 size_type size() const { return 1; }
1889
1890 /**
1891 *
1892 */
1893 std::string str() const { return data->name; }
1894};
1895
1896template <class Stat>
1897class ScalarProxyNode : public Node
1898{
1899 private:
1900 const ScalarProxy<Stat> proxy;
1901 mutable VResult vresult;
1902
1903 public:
1904 ScalarProxyNode(const ScalarProxy<Stat> &p)
1905 : proxy(p), vresult(1)
1906 { }
1907
1908 const VResult &
1909 result() const
1910 {
1911 vresult[0] = proxy.result();
1912 return vresult;
1913 }
1914
1915 Result
1916 total() const
1917 {
1918 return proxy.result();
1919 }
1920
1921 size_type
1922 size() const
1923 {
1924 return 1;
1925 }
1926
1927 /**
1928 *
1929 */
1930 std::string
1931 str() const
1932 {
1933 return proxy.str();
1934 }
1935};
1936
1937class VectorStatNode : public Node
1938{
1939 private:
1940 const VectorInfo *data;
1941
1942 public:
1943 VectorStatNode(const VectorInfo *d) : data(d) { }
1944 const VResult &result() const { return data->result(); }
1945 Result total() const { return data->total(); };
1946
1947 size_type size() const { return data->size(); }
1948
1949 std::string str() const { return data->name; }
1950};
1951
1952template <class T>
1953class ConstNode : public Node
1954{
1955 private:
1956 VResult vresult;
1957
1958 public:
1959 ConstNode(T s) : vresult(1, (Result)s) {}
1960 const VResult &result() const { return vresult; }
1961 Result total() const { return vresult[0]; };
1962 size_type size() const { return 1; }
1963 std::string str() const { return to_string(vresult[0]); }
1964};
1965
1966template <class T>
1967class ConstVectorNode : public Node
1968{
1969 private:
1970 VResult vresult;
1971
1972 public:
1973 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
1974 const VResult &result() const { return vresult; }
1975
1976 Result
1977 total() const
1978 {
1979 size_type size = this->size();
1980 Result tmp = 0;
1981 for (off_type i = 0; i < size; i++)
1982 tmp += vresult[i];
1983 return tmp;
1984 }
1985
1986 size_type size() const { return vresult.size(); }
1987 std::string
1988 str() const
1989 {
1990 size_type size = this->size();
1991 std::string tmp = "(";
1992 for (off_type i = 0; i < size; i++)
1993 tmp += csprintf("%s ",to_string(vresult[i]));
1994 tmp += ")";
1995 return tmp;
1996 }
1997};
1998
1999template <class Op>
2000struct OpString;
2001
2002template<>
2003struct OpString<std::plus<Result> >
2004{
2005 static std::string str() { return "+"; }
2006};
2007
2008template<>
2009struct OpString<std::minus<Result> >
2010{
2011 static std::string str() { return "-"; }
2012};
2013
2014template<>
2015struct OpString<std::multiplies<Result> >
2016{
2017 static std::string str() { return "*"; }
2018};
2019
2020template<>
2021struct OpString<std::divides<Result> >
2022{
2023 static std::string str() { return "/"; }
2024};
2025
2026template<>
2027struct OpString<std::modulus<Result> >
2028{
2029 static std::string str() { return "%"; }
2030};
2031
2032template<>
2033struct OpString<std::negate<Result> >
2034{
2035 static std::string str() { return "-"; }
2036};
2037
2038template <class Op>
2039class UnaryNode : public Node
2040{
2041 public:
2042 NodePtr l;
2043 mutable VResult vresult;
2044
2045 public:
2046 UnaryNode(NodePtr &p) : l(p) {}
2047
2048 const VResult &
2049 result() const
2050 {
2051 const VResult &lvec = l->result();
2052 size_type size = lvec.size();
2053
2054 assert(size > 0);
2055
2056 vresult.resize(size);
2057 Op op;
2058 for (off_type i = 0; i < size; ++i)
2059 vresult[i] = op(lvec[i]);
2060
2061 return vresult;
2062 }
2063
2064 Result
2065 total() const
2066 {
2067 const VResult &vec = this->result();
2068 Result total = 0.0;
2069 for (off_type i = 0; i < size(); i++)
2070 total += vec[i];
2071 return total;
2072 }
2073
2074 size_type size() const { return l->size(); }
2075
2076 std::string
2077 str() const
2078 {
2079 return OpString<Op>::str() + l->str();
2080 }
2081};
2082
2083template <class Op>
2084class BinaryNode : public Node
2085{
2086 public:
2087 NodePtr l;
2088 NodePtr r;
2089 mutable VResult vresult;
2090
2091 public:
2092 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2093
2094 const VResult &
2095 result() const
2096 {
2097 Op op;
2098 const VResult &lvec = l->result();
2099 const VResult &rvec = r->result();
2100
2101 assert(lvec.size() > 0 && rvec.size() > 0);
2102
2103 if (lvec.size() == 1 && rvec.size() == 1) {
2104 vresult.resize(1);
2105 vresult[0] = op(lvec[0], rvec[0]);
2106 } else if (lvec.size() == 1) {
2107 size_type size = rvec.size();
2108 vresult.resize(size);
2109 for (off_type i = 0; i < size; ++i)
2110 vresult[i] = op(lvec[0], rvec[i]);
2111 } else if (rvec.size() == 1) {
2112 size_type size = lvec.size();
2113 vresult.resize(size);
2114 for (off_type i = 0; i < size; ++i)
2115 vresult[i] = op(lvec[i], rvec[0]);
2116 } else if (rvec.size() == lvec.size()) {
2117 size_type size = rvec.size();
2118 vresult.resize(size);
2119 for (off_type i = 0; i < size; ++i)
2120 vresult[i] = op(lvec[i], rvec[i]);
2121 }
2122
2123 return vresult;
2124 }
2125
2126 Result
2127 total() const
2128 {
2129 const VResult &vec = this->result();
2130 Result total = 0.0;
2131 for (off_type i = 0; i < size(); i++)
2132 total += vec[i];
2133 return total;
2134 }
2135
2136 size_type
2137 size() const
2138 {
2139 size_type ls = l->size();
2140 size_type rs = r->size();
2141 if (ls == 1) {
2142 return rs;
2143 } else if (rs == 1) {
2144 return ls;
2145 } else {
2146 assert(ls == rs && "Node vector sizes are not equal");
2147 return ls;
2148 }
2149 }
2150
2151 std::string
2152 str() const
2153 {
2154 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2155 }
2156};
2157
2158template <class Op>
2159class SumNode : public Node
2160{
2161 public:
2162 NodePtr l;
2163 mutable VResult vresult;
2164
2165 public:
2166 SumNode(NodePtr &p) : l(p), vresult(1) {}
2167
2168 const VResult &
2169 result() const
2170 {
2171 const VResult &lvec = l->result();
2172 size_type size = lvec.size();
2173 assert(size > 0);
2174
2175 vresult[0] = 0.0;
2176
2177 Op op;
2178 for (off_type i = 0; i < size; ++i)
2179 vresult[0] = op(vresult[0], lvec[i]);
2180
2181 return vresult;
2182 }
2183
2184 Result
2185 total() const
2186 {
2187 const VResult &lvec = l->result();
2188 size_type size = lvec.size();
2189 assert(size > 0);
2190
2191 Result vresult = 0.0;
2192
2193 Op op;
2194 for (off_type i = 0; i < size; ++i)
2195 vresult = op(vresult, lvec[i]);
2196
2197 return vresult;
2198 }
2199
2200 size_type size() const { return 1; }
2201
2202 std::string
2203 str() const
2204 {
2205 return csprintf("total(%s)", l->str());
2206 }
2207};
2208
2209
2210//////////////////////////////////////////////////////////////////////
2211//
2212// Visible Statistics Types
2213//
2214//////////////////////////////////////////////////////////////////////
2215/**
2216 * @defgroup VisibleStats "Statistic Types"
2217 * These are the statistics that are used in the simulator.
2218 * @{
2219 */
2220
2221/**
2222 * This is a simple scalar statistic, like a counter.
2223 * @sa Stat, ScalarBase, StatStor
2224 */
2225class Scalar : public ScalarBase<Scalar, StatStor>
2226{
2227 public:
2228 using ScalarBase<Scalar, StatStor>::operator=;
2229};
2230
2231/**
2232 * A stat that calculates the per tick average of a value.
2233 * @sa Stat, ScalarBase, AvgStor
2234 */
2235class Average : public ScalarBase<Average, AvgStor>
2236{
2237 public:
2238 using ScalarBase<Average, AvgStor>::operator=;
2239};
2240
2241class Value : public ValueBase<Value>
2242{
2243};
2244
2245/**
2246 * A vector of scalar stats.
2247 * @sa Stat, VectorBase, StatStor
2248 */
2249class Vector : public VectorBase<Vector, StatStor>
2250{
2251};
2252
2253/**
2254 * A vector of Average stats.
2255 * @sa Stat, VectorBase, AvgStor
2256 */
2257class AverageVector : public VectorBase<AverageVector, AvgStor>
2258{
2259};
2260
2261/**
2262 * A 2-Dimensional vecto of scalar stats.
2263 * @sa Stat, Vector2dBase, StatStor
2264 */
2265class Vector2d : public Vector2dBase<Vector2d, StatStor>
2266{
2267};
2268
2269/**
2270 * A simple distribution stat.
2271 * @sa Stat, DistBase, DistStor
2272 */
2273class Distribution : public DistBase<Distribution, DistStor>
2274{
2275 public:
2276 /**
2277 * Set the parameters of this distribution. @sa DistStor::Params
2278 * @param min The minimum value of the distribution.
2279 * @param max The maximum value of the distribution.
2280 * @param bkt The number of values in each bucket.
2281 * @return A reference to this distribution.
2282 */
2283 Distribution &
2284 init(Counter min, Counter max, Counter bkt)
2285 {
2286 DistStor::Params *params = new DistStor::Params;
2287 params->min = min;
2288 params->max = max;
2289 params->bucket_size = bkt;
2290 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2291 this->setParams(params);
2292 this->doInit();
2293 return this->self();
2294 }
2295};
2296
2297/**
2298 * Calculates the mean and variance of all the samples.
2299 * @sa DistBase, SampleStor
2300 */
2301class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2302{
2303 public:
2304 /**
2305 * Construct and initialize this distribution.
2306 */
2307 StandardDeviation()
2308 {
2309 SampleStor::Params *params = new SampleStor::Params;
2310 this->doInit();
2311 this->setParams(params);
2312 }
2313};
2314
2315/**
2316 * Calculates the per tick mean and variance of the samples.
2317 * @sa DistBase, AvgSampleStor
2318 */
2319class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2320{
2321 public:
2322 /**
2323 * Construct and initialize this distribution.
2324 */
2325 AverageDeviation()
2326 {
2327 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2328 this->doInit();
2329 this->setParams(params);
2330 }
2331};
2332
2333/**
2334 * A vector of distributions.
2335 * @sa VectorDistBase, DistStor
2336 */
2337class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2338{
2339 public:
2340 /**
2341 * Initialize storage and parameters for this distribution.
2342 * @param size The size of the vector (the number of distributions).
2343 * @param min The minimum value of the distribution.
2344 * @param max The maximum value of the distribution.
2345 * @param bkt The number of values in each bucket.
2346 * @return A reference to this distribution.
2347 */
2348 VectorDistribution &
2349 init(size_type size, Counter min, Counter max, Counter bkt)
2350 {
2351 DistStor::Params *params = new DistStor::Params;
2352 params->min = min;
2353 params->max = max;
2354 params->bucket_size = bkt;
2355 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2356 this->setParams(params);
2357 this->doInit(size);
2358 return this->self();
2359 }
2360};
2361
2362/**
2363 * This is a vector of StandardDeviation stats.
2364 * @sa VectorDistBase, SampleStor
2365 */
2366class VectorStandardDeviation
2367 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2368{
2369 public:
2370 /**
2371 * Initialize storage for this distribution.
2372 * @param size The size of the vector.
2373 * @return A reference to this distribution.
2374 */
2375 VectorStandardDeviation &
2376 init(size_type size)
2377 {
2378 SampleStor::Params *params = new SampleStor::Params;
2379 this->doInit(size);
2380 this->setParams(params);
2381 return this->self();
2382 }
2383};
2384
2385/**
2386 * This is a vector of AverageDeviation stats.
2387 * @sa VectorDistBase, AvgSampleStor
2388 */
2389class VectorAverageDeviation
2390 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2391{
2392 public:
2393 /**
2394 * Initialize storage for this distribution.
2395 * @param size The size of the vector.
2396 * @return A reference to this distribution.
2397 */
2398 VectorAverageDeviation &
2399 init(size_type size)
2400 {
2401 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2402 this->doInit(size);
2403 this->setParams(params);
2404 return this->self();
2405 }
2406};
2407
2408template <class Stat>
2409class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2410{
2411 protected:
2412 mutable VResult vec;
2413 mutable VCounter cvec;
2414
2415 public:
2416 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2417
2418 size_type size() const { return this->s.size(); }
2419
2420 const VResult &
2421 result() const
2422 {
2423 this->s.result(vec);
2424 return vec;
2425 }
2426 Result total() const { return this->s.total(); }
2427 VCounter &value() const { return cvec; }
2428
2429 std::string str() const { return this->s.str(); }
2430};
2431
2432class Temp;
2433/**
2434 * A formula for statistics that is calculated when printed. A formula is
2435 * stored as a tree of Nodes that represent the equation to calculate.
2436 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2437 */
2438class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2439{
2440 protected:
2441 /** The root of the tree which represents the Formula */
2442 NodePtr root;
2443 friend class Temp;
2444
2445 public:
2446 /**
2447 * Create and initialize thie formula, and register it with the database.
2448 */
2449 Formula();
2450
2451 /**
2452 * Create a formula with the given root node, register it with the
2453 * database.
2454 * @param r The root of the expression tree.
2455 */
2456 Formula(Temp r);
2457
2458 /**
2459 * Set an unitialized Formula to the given root.
2460 * @param r The root of the expression tree.
2461 * @return a reference to this formula.
2462 */
2463 const Formula &operator=(Temp r);
2464
2465 /**
2466 * Add the given tree to the existing one.
2467 * @param r The root of the expression tree.
2468 * @return a reference to this formula.
2469 */
2470 const Formula &operator+=(Temp r);
2471 /**
2472 * Return the result of the Fomula in a vector. If there were no Vector
2473 * components to the Formula, then the vector is size 1. If there were,
2474 * like x/y with x being a vector of size 3, then the result returned will
2475 * be x[0]/y, x[1]/y, x[2]/y, respectively.
2476 * @return The result vector.
2477 */
2478 void result(VResult &vec) const;
2479
2480 /**
2481 * Return the total Formula result. If there is a Vector
2482 * component to this Formula, then this is the result of the
2483 * Formula if the formula is applied after summing all the
2484 * components of the Vector. For example, if Formula is x/y where
2485 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
2486 * there is no Vector component, total() returns the same value as
2487 * the first entry in the VResult val() returns.
2488 * @return The total of the result vector.
2489 */
2490 Result total() const;
2491
2492 /**
2493 * Return the number of elements in the tree.
2494 */
2495 size_type size() const;
2496
2497 void prepare() { }
2498
2499 /**
2500 * Formulas don't need to be reset
2501 */
2502 void reset();
2503
2504 /**
2505 *
2506 */
2507 bool zero() const;
2508
2509 std::string str() const;
2510};
2511
2512class FormulaNode : public Node
2513{
2514 private:
2515 const Formula &formula;
2516 mutable VResult vec;
2517
2518 public:
2519 FormulaNode(const Formula &f) : formula(f) {}
2520
2521 size_type size() const { return formula.size(); }
2522 const VResult &result() const { formula.result(vec); return vec; }
2523 Result total() const { return formula.total(); }
2524
2525 std::string str() const { return formula.str(); }
2526};
2527
2528/**
2529 * Helper class to construct formula node trees.
2530 */
2531class Temp
2532{
2533 protected:
2534 /**
2535 * Pointer to a Node object.
2536 */
2537 NodePtr node;
2538
2539 public:
2540 /**
2541 * Copy the given pointer to this class.
2542 * @param n A pointer to a Node object to copy.
2543 */
2544 Temp(NodePtr n) : node(n) { }
2545
2546 /**
2547 * Return the node pointer.
2548 * @return the node pointer.
2549 */
2550 operator NodePtr&() { return node; }
2551
2552 public:
2553 /**
2554 * Create a new ScalarStatNode.
2555 * @param s The ScalarStat to place in a node.
2556 */
2557 Temp(const Scalar &s)
2558 : node(new ScalarStatNode(s.info()))
2559 { }
2560
2561 /**
2562 * Create a new ScalarStatNode.
2563 * @param s The ScalarStat to place in a node.
2564 */
2565 Temp(const Value &s)
2566 : node(new ScalarStatNode(s.info()))
2567 { }
2568
2569 /**
2570 * Create a new ScalarStatNode.
2571 * @param s The ScalarStat to place in a node.
2572 */
2573 Temp(const Average &s)
2574 : node(new ScalarStatNode(s.info()))
2575 { }
2576
2577 /**
2578 * Create a new VectorStatNode.
2579 * @param s The VectorStat to place in a node.
2580 */
2581 Temp(const Vector &s)
2582 : node(new VectorStatNode(s.info()))
2583 { }
2584
2585 Temp(const AverageVector &s)
2586 : node(new VectorStatNode(s.info()))
2587 { }
2588
2589 /**
2590 *
2591 */
2592 Temp(const Formula &f)
2593 : node(new FormulaNode(f))
2594 { }
2595
2596 /**
2597 * Create a new ScalarProxyNode.
2598 * @param p The ScalarProxy to place in a node.
2599 */
2600 template <class Stat>
2601 Temp(const ScalarProxy<Stat> &p)
2602 : node(new ScalarProxyNode<Stat>(p))
2603 { }
2604
2605 /**
2606 * Create a ConstNode
2607 * @param value The value of the const node.
2608 */
2609 Temp(signed char value)
2610 : node(new ConstNode<signed char>(value))
2611 { }
2612
2613 /**
2614 * Create a ConstNode
2615 * @param value The value of the const node.
2616 */
2617 Temp(unsigned char value)
2618 : node(new ConstNode<unsigned char>(value))
2619 { }
2620
2621 /**
2622 * Create a ConstNode
2623 * @param value The value of the const node.
2624 */
2625 Temp(signed short value)
2626 : node(new ConstNode<signed short>(value))
2627 { }
2628
2629 /**
2630 * Create a ConstNode
2631 * @param value The value of the const node.
2632 */
2633 Temp(unsigned short value)
2634 : node(new ConstNode<unsigned short>(value))
2635 { }
2636
2637 /**
2638 * Create a ConstNode
2639 * @param value The value of the const node.
2640 */
2641 Temp(signed int value)
2642 : node(new ConstNode<signed int>(value))
2643 { }
2644
2645 /**
2646 * Create a ConstNode
2647 * @param value The value of the const node.
2648 */
2649 Temp(unsigned int value)
2650 : node(new ConstNode<unsigned int>(value))
2651 { }
2652
2653 /**
2654 * Create a ConstNode
2655 * @param value The value of the const node.
2656 */
2657 Temp(signed long value)
2658 : node(new ConstNode<signed long>(value))
2659 { }
2660
2661 /**
2662 * Create a ConstNode
2663 * @param value The value of the const node.
2664 */
2665 Temp(unsigned long value)
2666 : node(new ConstNode<unsigned long>(value))
2667 { }
2668
2669 /**
2670 * Create a ConstNode
2671 * @param value The value of the const node.
2672 */
2673 Temp(signed long long value)
2674 : node(new ConstNode<signed long long>(value))
2675 { }
2676
2677 /**
2678 * Create a ConstNode
2679 * @param value The value of the const node.
2680 */
2681 Temp(unsigned long long value)
2682 : node(new ConstNode<unsigned long long>(value))
2683 { }
2684
2685 /**
2686 * Create a ConstNode
2687 * @param value The value of the const node.
2688 */
2689 Temp(float value)
2690 : node(new ConstNode<float>(value))
2691 { }
2692
2693 /**
2694 * Create a ConstNode
2695 * @param value The value of the const node.
2696 */
2697 Temp(double value)
2698 : node(new ConstNode<double>(value))
2699 { }
2700};
2701
2702
2703/**
2704 * @}
2705 */
2706
2707inline Temp
2708operator+(Temp l, Temp r)
2709{
2710 return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2711}
2712
2713inline Temp
2714operator-(Temp l, Temp r)
2715{
2716 return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2717}
2718
2719inline Temp
2720operator*(Temp l, Temp r)
2721{
2722 return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
2723}
2724
2725inline Temp
2726operator/(Temp l, Temp r)
2727{
2728 return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
2729}
2730
2731inline Temp
2732operator-(Temp l)
2733{
2734 return NodePtr(new UnaryNode<std::negate<Result> >(l));
2735}
2736
2737template <typename T>
2738inline Temp
2739constant(T val)
2740{
2741 return NodePtr(new ConstNode<T>(val));
2742}
2743
2744template <typename T>
2745inline Temp
2746constantVector(T val)
2747{
2748 return NodePtr(new ConstVectorNode<T>(val));
2749}
2750
2751inline Temp
2752sum(Temp val)
2753{
2754 return NodePtr(new SumNode<std::plus<Result> >(val));
2755}
2756
2757/**
2758 * Enable the statistics package. Before the statistics package is
2759 * enabled, all statistics must be created and initialized and once
2760 * the package is enabled, no more statistics can be created.
2761 */
2762void enable();
2763
2764/**
2765 * Prepare all stats for data access. This must be done before
2766 * dumping and serialization.
2767 */
2768void prepare();
2769
2770/**
2771 * Dump all statistics data to the registered outputs
2772 */
2773void dump();
2774
2775/**
2776 * Reset all statistics to the base state
2777 */
2778void reset();
2779/**
2780 * Register a callback that should be called whenever statistics are
2781 * reset
2782 */
2783void registerResetCallback(Callback *cb);
2784
2785std::list<Info *> &statsList();
2786
2787} // namespace Stats
2788
2789#endif // __BASE_STATISTICS_HH__
1580 }
1581
1582 /**
1583 * Reset stat value to default
1584 */
1585 void
1586 reset(Info *info)
1587 {
1588 sum = Counter();
1589 squares = Counter();
1590 }
1591};
1592
1593/**
1594 * Implementation of a distribution stat. The type of distribution is
1595 * determined by the Storage template. @sa ScalarBase
1596 */
1597template <class Derived, class Stor>
1598class DistBase : public DataWrap<Derived, DistInfoProxy>
1599{
1600 public:
1601 typedef DistInfoProxy<Derived> Info;
1602 typedef Stor Storage;
1603 typedef typename Stor::Params Params;
1604
1605 protected:
1606 /** The storage for this stat. */
1607 char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1608
1609 protected:
1610 /**
1611 * Retrieve the storage.
1612 * @return The storage object for this stat.
1613 */
1614 Storage *
1615 data()
1616 {
1617 return reinterpret_cast<Storage *>(storage);
1618 }
1619
1620 /**
1621 * Retrieve a const pointer to the storage.
1622 * @return A const pointer to the storage object for this stat.
1623 */
1624 const Storage *
1625 data() const
1626 {
1627 return reinterpret_cast<const Storage *>(storage);
1628 }
1629
1630 void
1631 doInit()
1632 {
1633 new (storage) Storage(this->info());
1634 this->setInit();
1635 }
1636
1637 public:
1638 DistBase() { }
1639
1640 /**
1641 * Add a value to the distribtion n times. Calls sample on the storage
1642 * class.
1643 * @param v The value to add.
1644 * @param n The number of times to add it, defaults to 1.
1645 */
1646 template <typename U>
1647 void sample(const U &v, int n = 1) { data()->sample(v, n); }
1648
1649 /**
1650 * Return the number of entries in this stat.
1651 * @return The number of entries.
1652 */
1653 size_type size() const { return data()->size(); }
1654 /**
1655 * Return true if no samples have been added.
1656 * @return True if there haven't been any samples.
1657 */
1658 bool zero() const { return data()->zero(); }
1659
1660 void
1661 prepare()
1662 {
1663 Info *info = this->info();
1664 data()->prepare(info, info->data);
1665 }
1666
1667 /**
1668 * Reset stat value to default
1669 */
1670 void
1671 reset()
1672 {
1673 data()->reset(this->info());
1674 }
1675};
1676
1677template <class Stat>
1678class DistProxy;
1679
1680template <class Derived, class Stor>
1681class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1682{
1683 public:
1684 typedef VectorDistInfoProxy<Derived> Info;
1685 typedef Stor Storage;
1686 typedef typename Stor::Params Params;
1687 typedef DistProxy<Derived> Proxy;
1688 friend class DistProxy<Derived>;
1689 friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1690
1691 protected:
1692 Storage *storage;
1693 size_type _size;
1694
1695 protected:
1696 Storage *
1697 data(off_type index)
1698 {
1699 return &storage[index];
1700 }
1701
1702 const Storage *
1703 data(off_type index) const
1704 {
1705 return &storage[index];
1706 }
1707
1708 void
1709 doInit(size_type s)
1710 {
1711 assert(s > 0 && "size must be positive!");
1712 assert(!storage && "already initialized");
1713 _size = s;
1714
1715 char *ptr = new char[_size * sizeof(Storage)];
1716 storage = reinterpret_cast<Storage *>(ptr);
1717
1718 Info *info = this->info();
1719 for (off_type i = 0; i < _size; ++i)
1720 new (&storage[i]) Storage(info);
1721
1722 this->setInit();
1723 }
1724
1725 public:
1726 VectorDistBase()
1727 : storage(NULL)
1728 {}
1729
1730 ~VectorDistBase()
1731 {
1732 if (!storage)
1733 return ;
1734
1735 for (off_type i = 0; i < _size; ++i)
1736 data(i)->~Storage();
1737 delete [] reinterpret_cast<char *>(storage);
1738 }
1739
1740 Proxy operator[](off_type index)
1741 {
1742 assert(index >= 0 && index < size());
1743 return Proxy(this->self(), index);
1744 }
1745
1746 size_type
1747 size() const
1748 {
1749 return _size;
1750 }
1751
1752 bool
1753 zero() const
1754 {
1755 for (off_type i = 0; i < size(); ++i)
1756 if (!data(i)->zero())
1757 return false;
1758 return true;
1759 }
1760
1761 void
1762 prepare()
1763 {
1764 Info *info = this->info();
1765 size_type size = this->size();
1766 info->data.resize(size);
1767 for (off_type i = 0; i < size; ++i)
1768 data(i)->prepare(info, info->data[i]);
1769 }
1770
1771 bool
1772 check() const
1773 {
1774 return storage != NULL;
1775 }
1776};
1777
1778template <class Stat>
1779class DistProxy
1780{
1781 private:
1782 Stat &stat;
1783 off_type index;
1784
1785 protected:
1786 typename Stat::Storage *data() { return stat.data(index); }
1787 const typename Stat::Storage *data() const { return stat.data(index); }
1788
1789 public:
1790 DistProxy(Stat &s, off_type i)
1791 : stat(s), index(i)
1792 {}
1793
1794 DistProxy(const DistProxy &sp)
1795 : stat(sp.stat), index(sp.index)
1796 {}
1797
1798 const DistProxy &
1799 operator=(const DistProxy &sp)
1800 {
1801 stat = sp.stat;
1802 index = sp.index;
1803 return *this;
1804 }
1805
1806 public:
1807 template <typename U>
1808 void
1809 sample(const U &v, int n = 1)
1810 {
1811 data()->sample(v, n);
1812 }
1813
1814 size_type
1815 size() const
1816 {
1817 return 1;
1818 }
1819
1820 bool
1821 zero() const
1822 {
1823 return data()->zero();
1824 }
1825
1826 /**
1827 * Proxy has no state. Nothing to reset.
1828 */
1829 void reset() { }
1830};
1831
1832//////////////////////////////////////////////////////////////////////
1833//
1834// Formula Details
1835//
1836//////////////////////////////////////////////////////////////////////
1837
1838/**
1839 * Base class for formula statistic node. These nodes are used to build a tree
1840 * that represents the formula.
1841 */
1842class Node : public RefCounted
1843{
1844 public:
1845 /**
1846 * Return the number of nodes in the subtree starting at this node.
1847 * @return the number of nodes in this subtree.
1848 */
1849 virtual size_type size() const = 0;
1850 /**
1851 * Return the result vector of this subtree.
1852 * @return The result vector of this subtree.
1853 */
1854 virtual const VResult &result() const = 0;
1855 /**
1856 * Return the total of the result vector.
1857 * @return The total of the result vector.
1858 */
1859 virtual Result total() const = 0;
1860
1861 /**
1862 *
1863 */
1864 virtual std::string str() const = 0;
1865};
1866
1867/** Reference counting pointer to a function Node. */
1868typedef RefCountingPtr<Node> NodePtr;
1869
1870class ScalarStatNode : public Node
1871{
1872 private:
1873 const ScalarInfo *data;
1874 mutable VResult vresult;
1875
1876 public:
1877 ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
1878
1879 const VResult &
1880 result() const
1881 {
1882 vresult[0] = data->result();
1883 return vresult;
1884 }
1885
1886 Result total() const { return data->result(); };
1887
1888 size_type size() const { return 1; }
1889
1890 /**
1891 *
1892 */
1893 std::string str() const { return data->name; }
1894};
1895
1896template <class Stat>
1897class ScalarProxyNode : public Node
1898{
1899 private:
1900 const ScalarProxy<Stat> proxy;
1901 mutable VResult vresult;
1902
1903 public:
1904 ScalarProxyNode(const ScalarProxy<Stat> &p)
1905 : proxy(p), vresult(1)
1906 { }
1907
1908 const VResult &
1909 result() const
1910 {
1911 vresult[0] = proxy.result();
1912 return vresult;
1913 }
1914
1915 Result
1916 total() const
1917 {
1918 return proxy.result();
1919 }
1920
1921 size_type
1922 size() const
1923 {
1924 return 1;
1925 }
1926
1927 /**
1928 *
1929 */
1930 std::string
1931 str() const
1932 {
1933 return proxy.str();
1934 }
1935};
1936
1937class VectorStatNode : public Node
1938{
1939 private:
1940 const VectorInfo *data;
1941
1942 public:
1943 VectorStatNode(const VectorInfo *d) : data(d) { }
1944 const VResult &result() const { return data->result(); }
1945 Result total() const { return data->total(); };
1946
1947 size_type size() const { return data->size(); }
1948
1949 std::string str() const { return data->name; }
1950};
1951
1952template <class T>
1953class ConstNode : public Node
1954{
1955 private:
1956 VResult vresult;
1957
1958 public:
1959 ConstNode(T s) : vresult(1, (Result)s) {}
1960 const VResult &result() const { return vresult; }
1961 Result total() const { return vresult[0]; };
1962 size_type size() const { return 1; }
1963 std::string str() const { return to_string(vresult[0]); }
1964};
1965
1966template <class T>
1967class ConstVectorNode : public Node
1968{
1969 private:
1970 VResult vresult;
1971
1972 public:
1973 ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
1974 const VResult &result() const { return vresult; }
1975
1976 Result
1977 total() const
1978 {
1979 size_type size = this->size();
1980 Result tmp = 0;
1981 for (off_type i = 0; i < size; i++)
1982 tmp += vresult[i];
1983 return tmp;
1984 }
1985
1986 size_type size() const { return vresult.size(); }
1987 std::string
1988 str() const
1989 {
1990 size_type size = this->size();
1991 std::string tmp = "(";
1992 for (off_type i = 0; i < size; i++)
1993 tmp += csprintf("%s ",to_string(vresult[i]));
1994 tmp += ")";
1995 return tmp;
1996 }
1997};
1998
1999template <class Op>
2000struct OpString;
2001
2002template<>
2003struct OpString<std::plus<Result> >
2004{
2005 static std::string str() { return "+"; }
2006};
2007
2008template<>
2009struct OpString<std::minus<Result> >
2010{
2011 static std::string str() { return "-"; }
2012};
2013
2014template<>
2015struct OpString<std::multiplies<Result> >
2016{
2017 static std::string str() { return "*"; }
2018};
2019
2020template<>
2021struct OpString<std::divides<Result> >
2022{
2023 static std::string str() { return "/"; }
2024};
2025
2026template<>
2027struct OpString<std::modulus<Result> >
2028{
2029 static std::string str() { return "%"; }
2030};
2031
2032template<>
2033struct OpString<std::negate<Result> >
2034{
2035 static std::string str() { return "-"; }
2036};
2037
2038template <class Op>
2039class UnaryNode : public Node
2040{
2041 public:
2042 NodePtr l;
2043 mutable VResult vresult;
2044
2045 public:
2046 UnaryNode(NodePtr &p) : l(p) {}
2047
2048 const VResult &
2049 result() const
2050 {
2051 const VResult &lvec = l->result();
2052 size_type size = lvec.size();
2053
2054 assert(size > 0);
2055
2056 vresult.resize(size);
2057 Op op;
2058 for (off_type i = 0; i < size; ++i)
2059 vresult[i] = op(lvec[i]);
2060
2061 return vresult;
2062 }
2063
2064 Result
2065 total() const
2066 {
2067 const VResult &vec = this->result();
2068 Result total = 0.0;
2069 for (off_type i = 0; i < size(); i++)
2070 total += vec[i];
2071 return total;
2072 }
2073
2074 size_type size() const { return l->size(); }
2075
2076 std::string
2077 str() const
2078 {
2079 return OpString<Op>::str() + l->str();
2080 }
2081};
2082
2083template <class Op>
2084class BinaryNode : public Node
2085{
2086 public:
2087 NodePtr l;
2088 NodePtr r;
2089 mutable VResult vresult;
2090
2091 public:
2092 BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2093
2094 const VResult &
2095 result() const
2096 {
2097 Op op;
2098 const VResult &lvec = l->result();
2099 const VResult &rvec = r->result();
2100
2101 assert(lvec.size() > 0 && rvec.size() > 0);
2102
2103 if (lvec.size() == 1 && rvec.size() == 1) {
2104 vresult.resize(1);
2105 vresult[0] = op(lvec[0], rvec[0]);
2106 } else if (lvec.size() == 1) {
2107 size_type size = rvec.size();
2108 vresult.resize(size);
2109 for (off_type i = 0; i < size; ++i)
2110 vresult[i] = op(lvec[0], rvec[i]);
2111 } else if (rvec.size() == 1) {
2112 size_type size = lvec.size();
2113 vresult.resize(size);
2114 for (off_type i = 0; i < size; ++i)
2115 vresult[i] = op(lvec[i], rvec[0]);
2116 } else if (rvec.size() == lvec.size()) {
2117 size_type size = rvec.size();
2118 vresult.resize(size);
2119 for (off_type i = 0; i < size; ++i)
2120 vresult[i] = op(lvec[i], rvec[i]);
2121 }
2122
2123 return vresult;
2124 }
2125
2126 Result
2127 total() const
2128 {
2129 const VResult &vec = this->result();
2130 Result total = 0.0;
2131 for (off_type i = 0; i < size(); i++)
2132 total += vec[i];
2133 return total;
2134 }
2135
2136 size_type
2137 size() const
2138 {
2139 size_type ls = l->size();
2140 size_type rs = r->size();
2141 if (ls == 1) {
2142 return rs;
2143 } else if (rs == 1) {
2144 return ls;
2145 } else {
2146 assert(ls == rs && "Node vector sizes are not equal");
2147 return ls;
2148 }
2149 }
2150
2151 std::string
2152 str() const
2153 {
2154 return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2155 }
2156};
2157
2158template <class Op>
2159class SumNode : public Node
2160{
2161 public:
2162 NodePtr l;
2163 mutable VResult vresult;
2164
2165 public:
2166 SumNode(NodePtr &p) : l(p), vresult(1) {}
2167
2168 const VResult &
2169 result() const
2170 {
2171 const VResult &lvec = l->result();
2172 size_type size = lvec.size();
2173 assert(size > 0);
2174
2175 vresult[0] = 0.0;
2176
2177 Op op;
2178 for (off_type i = 0; i < size; ++i)
2179 vresult[0] = op(vresult[0], lvec[i]);
2180
2181 return vresult;
2182 }
2183
2184 Result
2185 total() const
2186 {
2187 const VResult &lvec = l->result();
2188 size_type size = lvec.size();
2189 assert(size > 0);
2190
2191 Result vresult = 0.0;
2192
2193 Op op;
2194 for (off_type i = 0; i < size; ++i)
2195 vresult = op(vresult, lvec[i]);
2196
2197 return vresult;
2198 }
2199
2200 size_type size() const { return 1; }
2201
2202 std::string
2203 str() const
2204 {
2205 return csprintf("total(%s)", l->str());
2206 }
2207};
2208
2209
2210//////////////////////////////////////////////////////////////////////
2211//
2212// Visible Statistics Types
2213//
2214//////////////////////////////////////////////////////////////////////
2215/**
2216 * @defgroup VisibleStats "Statistic Types"
2217 * These are the statistics that are used in the simulator.
2218 * @{
2219 */
2220
2221/**
2222 * This is a simple scalar statistic, like a counter.
2223 * @sa Stat, ScalarBase, StatStor
2224 */
2225class Scalar : public ScalarBase<Scalar, StatStor>
2226{
2227 public:
2228 using ScalarBase<Scalar, StatStor>::operator=;
2229};
2230
2231/**
2232 * A stat that calculates the per tick average of a value.
2233 * @sa Stat, ScalarBase, AvgStor
2234 */
2235class Average : public ScalarBase<Average, AvgStor>
2236{
2237 public:
2238 using ScalarBase<Average, AvgStor>::operator=;
2239};
2240
2241class Value : public ValueBase<Value>
2242{
2243};
2244
2245/**
2246 * A vector of scalar stats.
2247 * @sa Stat, VectorBase, StatStor
2248 */
2249class Vector : public VectorBase<Vector, StatStor>
2250{
2251};
2252
2253/**
2254 * A vector of Average stats.
2255 * @sa Stat, VectorBase, AvgStor
2256 */
2257class AverageVector : public VectorBase<AverageVector, AvgStor>
2258{
2259};
2260
2261/**
2262 * A 2-Dimensional vecto of scalar stats.
2263 * @sa Stat, Vector2dBase, StatStor
2264 */
2265class Vector2d : public Vector2dBase<Vector2d, StatStor>
2266{
2267};
2268
2269/**
2270 * A simple distribution stat.
2271 * @sa Stat, DistBase, DistStor
2272 */
2273class Distribution : public DistBase<Distribution, DistStor>
2274{
2275 public:
2276 /**
2277 * Set the parameters of this distribution. @sa DistStor::Params
2278 * @param min The minimum value of the distribution.
2279 * @param max The maximum value of the distribution.
2280 * @param bkt The number of values in each bucket.
2281 * @return A reference to this distribution.
2282 */
2283 Distribution &
2284 init(Counter min, Counter max, Counter bkt)
2285 {
2286 DistStor::Params *params = new DistStor::Params;
2287 params->min = min;
2288 params->max = max;
2289 params->bucket_size = bkt;
2290 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2291 this->setParams(params);
2292 this->doInit();
2293 return this->self();
2294 }
2295};
2296
2297/**
2298 * Calculates the mean and variance of all the samples.
2299 * @sa DistBase, SampleStor
2300 */
2301class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2302{
2303 public:
2304 /**
2305 * Construct and initialize this distribution.
2306 */
2307 StandardDeviation()
2308 {
2309 SampleStor::Params *params = new SampleStor::Params;
2310 this->doInit();
2311 this->setParams(params);
2312 }
2313};
2314
2315/**
2316 * Calculates the per tick mean and variance of the samples.
2317 * @sa DistBase, AvgSampleStor
2318 */
2319class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2320{
2321 public:
2322 /**
2323 * Construct and initialize this distribution.
2324 */
2325 AverageDeviation()
2326 {
2327 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2328 this->doInit();
2329 this->setParams(params);
2330 }
2331};
2332
2333/**
2334 * A vector of distributions.
2335 * @sa VectorDistBase, DistStor
2336 */
2337class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2338{
2339 public:
2340 /**
2341 * Initialize storage and parameters for this distribution.
2342 * @param size The size of the vector (the number of distributions).
2343 * @param min The minimum value of the distribution.
2344 * @param max The maximum value of the distribution.
2345 * @param bkt The number of values in each bucket.
2346 * @return A reference to this distribution.
2347 */
2348 VectorDistribution &
2349 init(size_type size, Counter min, Counter max, Counter bkt)
2350 {
2351 DistStor::Params *params = new DistStor::Params;
2352 params->min = min;
2353 params->max = max;
2354 params->bucket_size = bkt;
2355 params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2356 this->setParams(params);
2357 this->doInit(size);
2358 return this->self();
2359 }
2360};
2361
2362/**
2363 * This is a vector of StandardDeviation stats.
2364 * @sa VectorDistBase, SampleStor
2365 */
2366class VectorStandardDeviation
2367 : public VectorDistBase<VectorStandardDeviation, SampleStor>
2368{
2369 public:
2370 /**
2371 * Initialize storage for this distribution.
2372 * @param size The size of the vector.
2373 * @return A reference to this distribution.
2374 */
2375 VectorStandardDeviation &
2376 init(size_type size)
2377 {
2378 SampleStor::Params *params = new SampleStor::Params;
2379 this->doInit(size);
2380 this->setParams(params);
2381 return this->self();
2382 }
2383};
2384
2385/**
2386 * This is a vector of AverageDeviation stats.
2387 * @sa VectorDistBase, AvgSampleStor
2388 */
2389class VectorAverageDeviation
2390 : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2391{
2392 public:
2393 /**
2394 * Initialize storage for this distribution.
2395 * @param size The size of the vector.
2396 * @return A reference to this distribution.
2397 */
2398 VectorAverageDeviation &
2399 init(size_type size)
2400 {
2401 AvgSampleStor::Params *params = new AvgSampleStor::Params;
2402 this->doInit(size);
2403 this->setParams(params);
2404 return this->self();
2405 }
2406};
2407
2408template <class Stat>
2409class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2410{
2411 protected:
2412 mutable VResult vec;
2413 mutable VCounter cvec;
2414
2415 public:
2416 FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2417
2418 size_type size() const { return this->s.size(); }
2419
2420 const VResult &
2421 result() const
2422 {
2423 this->s.result(vec);
2424 return vec;
2425 }
2426 Result total() const { return this->s.total(); }
2427 VCounter &value() const { return cvec; }
2428
2429 std::string str() const { return this->s.str(); }
2430};
2431
2432class Temp;
2433/**
2434 * A formula for statistics that is calculated when printed. A formula is
2435 * stored as a tree of Nodes that represent the equation to calculate.
2436 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2437 */
2438class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2439{
2440 protected:
2441 /** The root of the tree which represents the Formula */
2442 NodePtr root;
2443 friend class Temp;
2444
2445 public:
2446 /**
2447 * Create and initialize thie formula, and register it with the database.
2448 */
2449 Formula();
2450
2451 /**
2452 * Create a formula with the given root node, register it with the
2453 * database.
2454 * @param r The root of the expression tree.
2455 */
2456 Formula(Temp r);
2457
2458 /**
2459 * Set an unitialized Formula to the given root.
2460 * @param r The root of the expression tree.
2461 * @return a reference to this formula.
2462 */
2463 const Formula &operator=(Temp r);
2464
2465 /**
2466 * Add the given tree to the existing one.
2467 * @param r The root of the expression tree.
2468 * @return a reference to this formula.
2469 */
2470 const Formula &operator+=(Temp r);
2471 /**
2472 * Return the result of the Fomula in a vector. If there were no Vector
2473 * components to the Formula, then the vector is size 1. If there were,
2474 * like x/y with x being a vector of size 3, then the result returned will
2475 * be x[0]/y, x[1]/y, x[2]/y, respectively.
2476 * @return The result vector.
2477 */
2478 void result(VResult &vec) const;
2479
2480 /**
2481 * Return the total Formula result. If there is a Vector
2482 * component to this Formula, then this is the result of the
2483 * Formula if the formula is applied after summing all the
2484 * components of the Vector. For example, if Formula is x/y where
2485 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
2486 * there is no Vector component, total() returns the same value as
2487 * the first entry in the VResult val() returns.
2488 * @return The total of the result vector.
2489 */
2490 Result total() const;
2491
2492 /**
2493 * Return the number of elements in the tree.
2494 */
2495 size_type size() const;
2496
2497 void prepare() { }
2498
2499 /**
2500 * Formulas don't need to be reset
2501 */
2502 void reset();
2503
2504 /**
2505 *
2506 */
2507 bool zero() const;
2508
2509 std::string str() const;
2510};
2511
2512class FormulaNode : public Node
2513{
2514 private:
2515 const Formula &formula;
2516 mutable VResult vec;
2517
2518 public:
2519 FormulaNode(const Formula &f) : formula(f) {}
2520
2521 size_type size() const { return formula.size(); }
2522 const VResult &result() const { formula.result(vec); return vec; }
2523 Result total() const { return formula.total(); }
2524
2525 std::string str() const { return formula.str(); }
2526};
2527
2528/**
2529 * Helper class to construct formula node trees.
2530 */
2531class Temp
2532{
2533 protected:
2534 /**
2535 * Pointer to a Node object.
2536 */
2537 NodePtr node;
2538
2539 public:
2540 /**
2541 * Copy the given pointer to this class.
2542 * @param n A pointer to a Node object to copy.
2543 */
2544 Temp(NodePtr n) : node(n) { }
2545
2546 /**
2547 * Return the node pointer.
2548 * @return the node pointer.
2549 */
2550 operator NodePtr&() { return node; }
2551
2552 public:
2553 /**
2554 * Create a new ScalarStatNode.
2555 * @param s The ScalarStat to place in a node.
2556 */
2557 Temp(const Scalar &s)
2558 : node(new ScalarStatNode(s.info()))
2559 { }
2560
2561 /**
2562 * Create a new ScalarStatNode.
2563 * @param s The ScalarStat to place in a node.
2564 */
2565 Temp(const Value &s)
2566 : node(new ScalarStatNode(s.info()))
2567 { }
2568
2569 /**
2570 * Create a new ScalarStatNode.
2571 * @param s The ScalarStat to place in a node.
2572 */
2573 Temp(const Average &s)
2574 : node(new ScalarStatNode(s.info()))
2575 { }
2576
2577 /**
2578 * Create a new VectorStatNode.
2579 * @param s The VectorStat to place in a node.
2580 */
2581 Temp(const Vector &s)
2582 : node(new VectorStatNode(s.info()))
2583 { }
2584
2585 Temp(const AverageVector &s)
2586 : node(new VectorStatNode(s.info()))
2587 { }
2588
2589 /**
2590 *
2591 */
2592 Temp(const Formula &f)
2593 : node(new FormulaNode(f))
2594 { }
2595
2596 /**
2597 * Create a new ScalarProxyNode.
2598 * @param p The ScalarProxy to place in a node.
2599 */
2600 template <class Stat>
2601 Temp(const ScalarProxy<Stat> &p)
2602 : node(new ScalarProxyNode<Stat>(p))
2603 { }
2604
2605 /**
2606 * Create a ConstNode
2607 * @param value The value of the const node.
2608 */
2609 Temp(signed char value)
2610 : node(new ConstNode<signed char>(value))
2611 { }
2612
2613 /**
2614 * Create a ConstNode
2615 * @param value The value of the const node.
2616 */
2617 Temp(unsigned char value)
2618 : node(new ConstNode<unsigned char>(value))
2619 { }
2620
2621 /**
2622 * Create a ConstNode
2623 * @param value The value of the const node.
2624 */
2625 Temp(signed short value)
2626 : node(new ConstNode<signed short>(value))
2627 { }
2628
2629 /**
2630 * Create a ConstNode
2631 * @param value The value of the const node.
2632 */
2633 Temp(unsigned short value)
2634 : node(new ConstNode<unsigned short>(value))
2635 { }
2636
2637 /**
2638 * Create a ConstNode
2639 * @param value The value of the const node.
2640 */
2641 Temp(signed int value)
2642 : node(new ConstNode<signed int>(value))
2643 { }
2644
2645 /**
2646 * Create a ConstNode
2647 * @param value The value of the const node.
2648 */
2649 Temp(unsigned int value)
2650 : node(new ConstNode<unsigned int>(value))
2651 { }
2652
2653 /**
2654 * Create a ConstNode
2655 * @param value The value of the const node.
2656 */
2657 Temp(signed long value)
2658 : node(new ConstNode<signed long>(value))
2659 { }
2660
2661 /**
2662 * Create a ConstNode
2663 * @param value The value of the const node.
2664 */
2665 Temp(unsigned long value)
2666 : node(new ConstNode<unsigned long>(value))
2667 { }
2668
2669 /**
2670 * Create a ConstNode
2671 * @param value The value of the const node.
2672 */
2673 Temp(signed long long value)
2674 : node(new ConstNode<signed long long>(value))
2675 { }
2676
2677 /**
2678 * Create a ConstNode
2679 * @param value The value of the const node.
2680 */
2681 Temp(unsigned long long value)
2682 : node(new ConstNode<unsigned long long>(value))
2683 { }
2684
2685 /**
2686 * Create a ConstNode
2687 * @param value The value of the const node.
2688 */
2689 Temp(float value)
2690 : node(new ConstNode<float>(value))
2691 { }
2692
2693 /**
2694 * Create a ConstNode
2695 * @param value The value of the const node.
2696 */
2697 Temp(double value)
2698 : node(new ConstNode<double>(value))
2699 { }
2700};
2701
2702
2703/**
2704 * @}
2705 */
2706
2707inline Temp
2708operator+(Temp l, Temp r)
2709{
2710 return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2711}
2712
2713inline Temp
2714operator-(Temp l, Temp r)
2715{
2716 return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2717}
2718
2719inline Temp
2720operator*(Temp l, Temp r)
2721{
2722 return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
2723}
2724
2725inline Temp
2726operator/(Temp l, Temp r)
2727{
2728 return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
2729}
2730
2731inline Temp
2732operator-(Temp l)
2733{
2734 return NodePtr(new UnaryNode<std::negate<Result> >(l));
2735}
2736
2737template <typename T>
2738inline Temp
2739constant(T val)
2740{
2741 return NodePtr(new ConstNode<T>(val));
2742}
2743
2744template <typename T>
2745inline Temp
2746constantVector(T val)
2747{
2748 return NodePtr(new ConstVectorNode<T>(val));
2749}
2750
2751inline Temp
2752sum(Temp val)
2753{
2754 return NodePtr(new SumNode<std::plus<Result> >(val));
2755}
2756
2757/**
2758 * Enable the statistics package. Before the statistics package is
2759 * enabled, all statistics must be created and initialized and once
2760 * the package is enabled, no more statistics can be created.
2761 */
2762void enable();
2763
2764/**
2765 * Prepare all stats for data access. This must be done before
2766 * dumping and serialization.
2767 */
2768void prepare();
2769
2770/**
2771 * Dump all statistics data to the registered outputs
2772 */
2773void dump();
2774
2775/**
2776 * Reset all statistics to the base state
2777 */
2778void reset();
2779/**
2780 * Register a callback that should be called whenever statistics are
2781 * reset
2782 */
2783void registerResetCallback(Callback *cb);
2784
2785std::list<Info *> &statsList();
2786
2787} // namespace Stats
2788
2789#endif // __BASE_STATISTICS_HH__