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