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