statistics.cc revision 441
1/* 2 * Copyright (c) 2003 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 29#include <iomanip> 30#include <iostream> 31#include <list> 32#include <map> 33#include <string> 34#include <sstream> 35 36#include "base/callback.hh" 37#include "base/cprintf.hh" 38#include "base/hostinfo.hh" 39#include "base/misc.hh" 40#include "base/python.hh" 41#include "base/statistics.hh" 42#include "base/str.hh" 43#include "base/time.hh" 44#include "base/trace.hh" 45 46#ifdef __M5_NAN 47float 48__nan() 49{ 50 union { 51 uint32_t ui; 52 float f; 53 } nan; 54 55 nan.ui = 0x7fc00000; 56 return nan.f; 57} 58#endif 59 60#ifdef STAT_DEBUG 61static int total_stats = 0; 62#endif 63 64using namespace std; 65 66// This is a hack to get this parameter from the old stats package. 67namespace Statistics { 68bool PrintDescriptions = true; 69DisplayMode DefaultMode = mode_simplescalar; 70 71namespace Database 72{ 73 class Data 74 { 75 private: 76 typedef list<StatData *> list_t; 77 typedef map<void *, StatData *> map_t; 78 79 list<MainBin *> bins; 80 81 list_t allStats; 82 list_t printStats; 83 map_t statMap; 84 85 public: 86 void dump(ostream &stream, const string &name, DisplayMode mode); 87 void display(ostream &stream, DisplayMode mode); 88 void python(ostream &stream, const string &name); 89 void python(Python &py, const string &name, const string &bin); 90 91 StatData *find(void *stat); 92 void mapStat(void *stat, StatData *data); 93 94 void check(); 95 void reset(); 96 void regBin(MainBin *bin, string name); 97 void regPrint(void *stat); 98 99 static std::string name() { return "Statistics Database"; } 100 }; 101 102 103void 104Data::dump(ostream &stream, const string &name, DisplayMode mode) 105{ 106 MainBin *orig = MainBin::curBin(); 107 108 switch (mode) { 109 case mode_python: 110 python(stream, name); 111 break; 112 case mode_m5: 113 case mode_simplescalar: 114 display(stream, mode); 115 break; 116 default: 117 warn("invalid display mode!\n"); 118 display(stream, mode_m5); 119 break; 120 } 121 122 if (orig) 123 orig->activate(); 124} 125 126void 127Data::display(ostream &stream, DisplayMode mode) 128{ 129 if (!bins.empty()) { 130 list<MainBin *>::iterator i = bins.begin(); 131 list<MainBin *>::iterator bins_end = bins.end(); 132 ccprintf(stream, "PRINTING BINNED STATS\n"); 133 while (i != bins_end) { 134 (*i)->activate(); 135 ccprintf(stream,"---%s Bin------------\n", (*i)->name()); 136 137 list_t::iterator j = printStats.begin(); 138 list_t::iterator end = printStats.end(); 139 while (j != end) { 140 StatData *stat = *j; 141 if (stat->dodisplay()) 142 stat->display(stream, mode); 143 ++j; 144 } 145 ++i; 146 ccprintf(stream, "---------------------------------\n"); 147 } 148 } else { 149 list_t::iterator i = printStats.begin(); 150 list_t::iterator end = printStats.end(); 151 while (i != end) { 152 StatData *stat = *i; 153 if (stat->dodisplay() && !stat->binned()) 154 stat->display(stream, mode); 155 ++i; 156 } 157 } 158} 159 160void 161Data::python(ostream &stream, const string &name) 162{ 163 Python py(stream); 164 165 ccprintf(stream, "import sys\n"); 166 ccprintf(stream, "sys.path.append('.')\n"); 167 ccprintf(stream, "from m5stats import *\n\n"); 168 169 if (bins.empty()) { 170 python(py, name, ""); 171 } else { 172 list<MainBin *>::iterator i = bins.begin(); 173 list<MainBin *>::iterator end = bins.end(); 174 175 while (i != end) { 176 (*i)->activate(); 177 python(py, name, (*i)->name()); 178 ++i; 179 } 180 } 181 182 py.next(); 183 ccprintf(stream, "if __name__ == '__main__':\n"); 184 ccprintf(stream, " program_display()\n"); 185} 186 187void 188Data::python(Python &py, const string &name, const string &bin) 189{ 190 py.start("collections.append"); 191 py.start("Collection"); 192 py.qarg(name); 193 py.qarg(bin); 194 py.qarg(hostname()); 195 py.qarg(Time::start.date()); 196 list_t::iterator i = allStats.begin(); 197 list_t::iterator end = allStats.end(); 198 while (i != end) { 199 StatData *stat = *i; 200 stat->python(py); 201 ++i; 202 } 203 py.end(); 204 py.end(); 205} 206 207StatData * 208Data::find(void *stat) 209{ 210 map_t::const_iterator i = statMap.find(stat); 211 212 if (i == statMap.end()) 213 return NULL; 214 215 return (*i).second; 216} 217 218void 219Data::check() 220{ 221 list_t::iterator i = allStats.begin(); 222 list_t::iterator end = allStats.end(); 223 224 while (i != end) { 225 StatData *data = *i; 226 assert(data); 227 data->check(); 228 ++i; 229 } 230 231 i = allStats.begin(); 232 int j = 0; 233 while (i != end) { 234 StatData *data = *i; 235 if (!(data->flags & print)) 236 data->name = "__Stat" + to_string(j++); 237 ++i; 238 } 239} 240 241void 242Data::reset() 243{ 244 // reset non-binned stats 245 list_t::iterator i = allStats.begin(); 246 list_t::iterator end = allStats.end(); 247 while (i != end) { 248 StatData *data = *i; 249 if (!data->binned()) 250 data->reset(); 251 ++i; 252 } 253 254 // save the bin so we can go back to where we were 255 MainBin *orig = MainBin::curBin(); 256 257 // reset binned stats 258 list<MainBin *>::iterator bi = bins.begin(); 259 list<MainBin *>::iterator be = bins.end(); 260 while (bi != be) { 261 MainBin *bin = *bi; 262 bin->activate(); 263 264 i = allStats.begin(); 265 while (i != end) { 266 StatData *data = *i; 267 if (data->binned()) 268 data->reset(); 269 ++i; 270 } 271 ++bi; 272 } 273 274 // restore bin 275 MainBin::curBin() = orig; 276} 277 278void 279Data::mapStat(void *stat, StatData *data) 280{ 281 if (statMap.find(stat) != statMap.end()) 282 panic("shouldn't register stat twice!"); 283 284 allStats.push_back(data); 285 286#ifndef NDEBUG 287 bool success = 288#endif 289 (statMap.insert(make_pair(stat, data))).second; 290 assert(statMap.find(stat) != statMap.end()); 291 assert(success && "this should never fail"); 292} 293 294void 295Data::regBin(MainBin *bin, string _name) 296{ 297 bins.push_back(bin); 298 DPRINTF(Stats, "registering %s\n", _name); 299} 300 301void 302Data::regPrint(void *stat) 303{ 304 StatData *data = find(stat); 305 306 if (data->flags & print) 307 return; 308 309 data->flags |= print; 310 311 list_t::iterator j = printStats.insert(printStats.end(), data); 312 inplace_merge(printStats.begin(), j, printStats.end(), StatData::less); 313} 314 315Data & 316StatDB() 317{ 318 static Data db; 319 return db; 320} 321 322} 323 324StatData * 325DataAccess::find() const 326{ 327 return Database::StatDB().find(const_cast<void *>((const void *)this)); 328} 329 330const StatData * 331getStatData(const void *stat) 332{ 333 return Database::StatDB().find(const_cast<void *>(stat)); 334} 335 336void 337DataAccess::map(StatData *data) 338{ 339 Database::StatDB().mapStat(this, data); 340} 341 342StatData * 343DataAccess::statData() 344{ 345 StatData *ptr = find(); 346 assert(ptr); 347 return ptr; 348} 349 350const StatData * 351DataAccess::statData() const 352{ 353 const StatData *ptr = find(); 354 assert(ptr); 355 return ptr; 356} 357 358void 359DataAccess::setInit() 360{ 361 statData()->flags |= init; 362} 363 364void 365DataAccess::setPrint() 366{ 367 Database::StatDB().regPrint(this); 368} 369 370StatData::~StatData() 371{ 372} 373 374bool 375StatData::less(StatData *stat1, StatData *stat2) 376{ 377 const string &name1 = stat1->name; 378 const string &name2 = stat2->name; 379 380 vector<string> v1; 381 vector<string> v2; 382 383 tokenize(v1, name1, '.'); 384 tokenize(v2, name2, '.'); 385 386 int last = min(v1.size(), v2.size()) - 1; 387 for (int i = 0; i < last; ++i) 388 if (v1[i] != v2[i]) 389 return v1[i] < v2[i]; 390 391 // Special compare for last element. 392 if (v1[last] == v2[last]) 393 return v1.size() < v2.size(); 394 else 395 return v1[last] < v2[last]; 396 397 return false; 398} 399 400bool 401StatData::baseCheck() const 402{ 403 if (!(flags & init)) { 404#ifdef STAT_DEBUG 405 cprintf("this is stat number %d\n",(*i)->number); 406#endif 407 panic("Not all stats have been initialized"); 408 return false; 409 } 410 411 if ((flags & print) && name.empty()) { 412 panic("all printable stats must be named"); 413 return false; 414 } 415 416 return true; 417} 418 419string 420ValueToString(result_t value, DisplayMode mode, int precision) 421{ 422 stringstream val; 423 424 if (!isnan(value)) { 425 if (precision != -1) 426 val.precision(precision); 427 else if (value == rint(value)) 428 val.precision(0); 429 430 val.unsetf(ios::showpoint); 431 val.setf(ios::fixed); 432 val << value; 433 } else { 434 val << (mode == mode_m5 ? "no value" : "<err: div-0>"); 435 } 436 437 return val.str(); 438} 439 440struct ScalarPrint 441{ 442 result_t value; 443 string name; 444 string desc; 445 StatFlags flags; 446 DisplayMode mode; 447 int precision; 448 result_t pdf; 449 result_t cdf; 450 451 ScalarPrint() 452 : value(0.0), flags(0), mode(DefaultMode), precision(0), 453 pdf(NAN), cdf(NAN) 454 {} 455 456 void operator()(ostream &stream) const; 457}; 458 459void 460ScalarPrint::operator()(ostream &stream) const 461{ 462 if (flags & nozero && value == 0.0 || 463 flags & nonan && isnan(value)) 464 return; 465 466 stringstream pdfstr, cdfstr; 467 468 if (!isnan(pdf)) 469 ccprintf(pdfstr, "%.2f%%", pdf * 100.0); 470 471 if (!isnan(cdf)) 472 ccprintf(cdfstr, "%.2f%%", cdf * 100.0); 473 474 if (mode == mode_simplescalar && flags & __substat) { 475 ccprintf(stream, "%32s %12s %10s %10s", name, 476 ValueToString(value, mode, precision), pdfstr, cdfstr); 477 } else { 478 ccprintf(stream, "%-40s %12s %10s %10s", name, 479 ValueToString(value, mode, precision), pdfstr, cdfstr); 480 } 481 482 if (PrintDescriptions) { 483 if (!desc.empty()) 484 ccprintf(stream, " # %s", desc); 485 } 486 stream << endl; 487} 488 489struct VectorPrint 490{ 491 string name; 492 string desc; 493 vector<string> subnames; 494 vector<string> subdescs; 495 StatFlags flags; 496 DisplayMode mode; 497 int precision; 498 rvec_t vec; 499 result_t total; 500 501 VectorPrint() 502 : subnames(0), subdescs(0), flags(0), mode(DefaultMode), 503 precision(-1), total(NAN) 504 {} 505 506 void operator()(ostream &stream) const; 507}; 508 509void 510VectorPrint::operator()(std::ostream &stream) const 511{ 512 int _size = vec.size(); 513 result_t _total = 0.0; 514 515 if (flags & (pdf | cdf)) { 516 for (int i = 0; i < _size; ++i) { 517 _total += vec[i]; 518 } 519 } 520 521 string base = name + ((mode == mode_simplescalar) ? "_" : "::"); 522 523 ScalarPrint print; 524 print.name = name; 525 print.desc = desc; 526 print.precision = precision; 527 print.flags = flags; 528 529 bool havesub = !subnames.empty(); 530 531 if (_size == 1) { 532 print.value = vec[0]; 533 print(stream); 534 } else if (mode == mode_m5) { 535 for (int i = 0; i < _size; ++i) { 536 if (havesub && (i >= subnames.size() || subnames[i].empty())) 537 continue; 538 539 print.name = base + (havesub ? subnames[i] : to_string(i)); 540 print.desc = subdescs.empty() ? desc : subdescs[i]; 541 print.value = vec[i]; 542 543 if (_total && (flags & pdf)) { 544 print.pdf = vec[i] / _total; 545 print.cdf += print.pdf; 546 } 547 548 print(stream); 549 } 550 551 if (flags & ::Statistics::total) { 552 print.name = base + "total"; 553 print.desc = desc; 554 print.value = total; 555 print(stream); 556 } 557 } else { 558 if (flags & ::Statistics::total) { 559 print.value = total; 560 print(stream); 561 } 562 563 result_t _pdf = 0.0; 564 result_t _cdf = 0.0; 565 if (flags & dist) { 566 ccprintf(stream, "%s.start_dist\n", name); 567 for (int i = 0; i < _size; ++i) { 568 print.name = havesub ? subnames[i] : to_string(i); 569 print.desc = subdescs.empty() ? desc : subdescs[i]; 570 print.flags |= __substat; 571 print.value = vec[i]; 572 573 if (_total) { 574 _pdf = vec[i] / _total; 575 _cdf += _pdf; 576 } 577 578 if (flags & pdf) 579 print.pdf = _pdf; 580 if (flags & cdf) 581 print.cdf = _cdf; 582 583 print(stream); 584 } 585 ccprintf(stream, "%s.end_dist\n", name); 586 } else { 587 for (int i = 0; i < _size; ++i) { 588 if (havesub && subnames[i].empty()) 589 continue; 590 591 print.name = base; 592 print.name += havesub ? subnames[i] : to_string(i); 593 print.desc = subdescs.empty() ? desc : subdescs[i]; 594 print.value = vec[i]; 595 596 if (_total) { 597 _pdf = vec[i] / _total; 598 _cdf += _pdf; 599 } else { 600 _pdf = _cdf = NAN; 601 } 602 603 if (flags & pdf) { 604 print.pdf = _pdf; 605 print.cdf = _cdf; 606 } 607 608 print(stream); 609 } 610 } 611 } 612} 613 614struct DistPrint 615{ 616 string name; 617 string desc; 618 StatFlags flags; 619 DisplayMode mode; 620 int precision; 621 622 result_t min_val; 623 result_t max_val; 624 result_t underflow; 625 result_t overflow; 626 rvec_t vec; 627 result_t sum; 628 result_t squares; 629 result_t samples; 630 631 int min; 632 int max; 633 int bucket_size; 634 int size; 635 bool fancy; 636 637 void operator()(ostream &stream) const; 638}; 639 640void 641DistPrint::operator()(ostream &stream) const 642{ 643 if (fancy) { 644 ScalarPrint print; 645 string base = name + ((mode == mode_m5) ? "::" : "_"); 646 647 print.precision = precision; 648 print.flags = flags; 649 print.mode = mode; 650 print.desc = desc; 651 652 print.name = base + "mean"; 653 print.value = samples ? sum / samples : NAN; 654 print(stream); 655 656 print.name = base + "stdev"; 657 print.value = samples ? sqrt((samples * squares - sum * sum) / 658 (samples * (samples - 1.0))) : NAN; 659 print(stream); 660 661 print.name = "**Ignore: " + base + "TOT"; 662 print.value = samples; 663 print(stream); 664 return; 665 } 666 667 assert(size == vec.size()); 668 669 result_t total = 0.0; 670 671 total += underflow; 672 for (int i = 0; i < size; ++i) 673 total += vec[i]; 674 total += overflow; 675 676 string base = name + (mode == mode_m5 ? "::" : "."); 677 678 ScalarPrint print; 679 print.desc = (mode == mode_m5) ? desc : ""; 680 print.flags = flags; 681 print.mode = mode; 682 print.precision = precision; 683 684 if (mode == mode_simplescalar) { 685 ccprintf(stream, "%-42s", base + "start_dist"); 686 if (PrintDescriptions && !desc.empty()) 687 ccprintf(stream, " # %s", desc); 688 stream << endl; 689 } 690 691 print.name = base + "samples"; 692 print.value = samples; 693 print(stream); 694 695 print.name = base + "min_value"; 696 print.value = min_val; 697 print(stream); 698 699 if (mode == mode_m5 || underflow > 0.0) { 700 print.name = base + "underflows"; 701 print.value = underflow; 702 if (mode == mode_m5 && total) { 703 print.pdf = underflow / total; 704 print.cdf += print.pdf; 705 } 706 print(stream); 707 } 708 709 710 if (mode == mode_m5) { 711 for (int i = 0; i < size; ++i) { 712 stringstream namestr; 713 namestr << name; 714 715 int low = i * bucket_size + min; 716 int high = ::min((i + 1) * bucket_size + min - 1, max); 717 namestr << low; 718 if (low < high) 719 namestr << "-" << high; 720 721 print.name = namestr.str(); 722 print.value = vec[i]; 723 if (total) { 724 print.pdf = vec[i] / total; 725 print.cdf += print.pdf; 726 } 727 print(stream); 728 } 729 730 } else { 731 int _min; 732 result_t _pdf; 733 result_t _cdf = 0.0; 734 735 print.flags = flags | __substat; 736 737 for (int i = 0; i < size; ++i) { 738 if (flags & nozero && vec[i] == 0.0 || 739 flags & nonan && isnan(vec[i])) 740 continue; 741 742 _min = i * bucket_size + min; 743 _pdf = vec[i] / total * 100.0; 744 _cdf += _pdf; 745 746 747 print.name = ValueToString(_min, mode, 0); 748 print.value = vec[i]; 749 print.pdf = (flags & pdf) ? _pdf : NAN; 750 print.cdf = (flags & cdf) ? _cdf : NAN; 751 print(stream); 752 } 753 754 print.flags = flags; 755 } 756 757 if (mode == mode_m5 || overflow > 0.0) { 758 print.name = base + "overflows"; 759 print.value = overflow; 760 if (mode == mode_m5 && total) { 761 print.pdf = overflow / total; 762 print.cdf += print.pdf; 763 } else { 764 print.pdf = NAN; 765 print.cdf = NAN; 766 } 767 print(stream); 768 } 769 770 print.pdf = NAN; 771 print.cdf = NAN; 772 773 if (mode != mode_simplescalar) { 774 print.name = base + "total"; 775 print.value = total; 776 print(stream); 777 } 778 779 print.name = base + "max_value"; 780 print.value = max_val; 781 print(stream); 782 783 if (mode != mode_simplescalar && samples != 0) { 784 print.name = base + "mean"; 785 print.value = sum / samples; 786 print(stream); 787 788 print.name = base + "stdev"; 789 print.value = sqrt((samples * squares - sum * sum) / 790 (samples * (samples - 1.0))); 791 print(stream); 792 } 793 794 if (mode == mode_simplescalar) 795 ccprintf(stream, "%send_dist\n\n", base); 796} 797 798void 799ScalarDataBase::display(ostream &stream, DisplayMode mode) const 800{ 801 ScalarPrint print; 802 print.value = val(); 803 print.name = name; 804 print.desc = desc; 805 print.flags = flags; 806 print.mode = mode; 807 print.precision = precision; 808 809 print(stream); 810} 811 812void 813VectorDataBase::display(ostream &stream, DisplayMode mode) const 814{ 815 int size = this->size(); 816 const_cast<VectorDataBase *>(this)->update(); 817 818 VectorPrint print; 819 820 print.name = name; 821 print.desc = desc; 822 print.flags = flags; 823 print.mode = mode; 824 print.precision = precision; 825 print.vec = val(); 826 print.total = total(); 827 828 if (!subnames.empty()) { 829 for (int i = 0; i < size; ++i) { 830 if (!subnames[i].empty()) { 831 print.subnames = subnames; 832 print.subnames.resize(size); 833 for (int i = 0; i < size; ++i) { 834 if (!subnames[i].empty() && !subdescs[i].empty()) { 835 print.subdescs = subdescs; 836 print.subdescs.resize(size); 837 break; 838 } 839 } 840 break; 841 } 842 } 843 } 844 845 print(stream); 846} 847 848void 849Vector2dDataBase::display(ostream &stream, DisplayMode mode) const 850{ 851 const_cast<Vector2dDataBase *>(this)->update(); 852 853 bool havesub = false; 854 VectorPrint print; 855 856 print.subnames = y_subnames; 857 print.flags = flags; 858 print.mode = mode; 859 print.precision = precision; 860 861 if (!subnames.empty()) { 862 for (int i = 0; i < x; ++i) 863 if (!subnames[i].empty()) 864 havesub = true; 865 } 866 867 rvec_t tot_vec(y); 868 result_t super_total = 0.0; 869 for (int i = 0; i < x; ++i) { 870 if (havesub && (i >= subnames.size() || subnames[i].empty())) 871 continue; 872 873 int iy = i * y; 874 rvec_t yvec(y); 875 876 result_t total = 0.0; 877 for (int j = 0; j < y; ++j) { 878 yvec[j] = vec[iy + j]; 879 tot_vec[j] += yvec[j]; 880 total += yvec[j]; 881 super_total += yvec[j]; 882 } 883 884 print.name = name + "_" + (havesub ? subnames[i] : to_string(i)); 885 print.desc = desc; 886 print.vec = yvec; 887 print.total = total; 888 print(stream); 889 } 890 891 if ((flags & ::Statistics::total) && (x > 1)) { 892 print.name = name; 893 print.desc = desc; 894 print.vec = tot_vec; 895 print.total = super_total; 896 print(stream); 897 } 898} 899 900void 901DistDataBase::display(ostream &stream, DisplayMode mode) const 902{ 903 const_cast<DistDataBase *>(this)->update(); 904 905 DistPrint print; 906 907 print.name = name; 908 print.desc = desc; 909 print.flags = flags; 910 print.mode = mode; 911 print.precision = precision; 912 913 print.min_val = data.min_val; 914 print.max_val = data.max_val; 915 print.underflow = data.underflow; 916 print.overflow = data.overflow; 917 print.vec = data.vec; 918 print.sum = data.sum; 919 print.squares = data.squares; 920 print.samples = data.samples; 921 922 print.min = data.min; 923 print.max = data.max; 924 print.bucket_size = data.bucket_size; 925 print.size = data.size; 926 print.fancy = data.fancy; 927 928 print(stream); 929} 930 931void 932VectorDistDataBase::display(ostream &stream, DisplayMode mode) const 933{ 934 const_cast<VectorDistDataBase *>(this)->update(); 935 936 for (int i = 0; i < size(); ++i) { 937 DistPrint print; 938 939 print.name = name + 940 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]); 941 print.desc = subdescs[i].empty() ? desc : subdescs[i]; 942 print.flags = flags; 943 print.mode = mode; 944 print.precision = precision; 945 946 print.min_val = data[i].min_val; 947 print.max_val = data[i].max_val; 948 print.underflow = data[i].underflow; 949 print.overflow = data[i].overflow; 950 print.vec = data[i].vec; 951 print.sum = data[i].sum; 952 print.squares = data[i].squares; 953 print.samples = data[i].samples; 954 955 print.min = data[i].min; 956 print.max = data[i].max; 957 print.bucket_size = data[i].bucket_size; 958 print.size = data[i].size; 959 print.fancy = data[i].fancy; 960 961 print(stream); 962 } 963} 964 965void 966ScalarDataBase::python(Python &py) const 967{ 968 py.start("Scalar"); 969 py.qarg(name); 970 py.qarg(desc); 971 py.kwarg("binned", binned()); 972 py.kwarg("precision", precision); 973 py.kwarg("flags", flags); 974 if (prereq) 975 py.qkwarg("prereq", prereq->name); 976 py.kwarg("value", val()); 977 py.end(); 978} 979 980void 981VectorDataBase::python(Python &py) const 982{ 983 const_cast<VectorDataBase *>(this)->update(); 984 985 py.start("Vector"); 986 py.qarg(name); 987 py.qarg(desc); 988 py.kwarg("binned", binned()); 989 py.kwarg("precision", precision); 990 py.kwarg("flags", flags); 991 if (prereq) 992 py.qkwarg("prereq", prereq->name); 993 py.kwarg("value", val()); 994 if (!subnames.empty()) 995 py.qkwarg("subnames", subnames); 996 if (!subdescs.empty()) 997 py.qkwarg("subdescs", subdescs); 998 py.end(); 999} 1000 1001void 1002DistDataData::python(Python &py, const string &name) const 1003{ 1004 string s = name.empty() ? "" : name + "="; 1005 1006 if (samples == 0 || fancy) 1007 s += "SimpleDist"; 1008 else 1009 s += "FullDist"; 1010 1011 py.start(s); 1012 py.arg(sum); 1013 py.arg(squares); 1014 py.arg(samples); 1015 if (samples && !fancy) { 1016 py.arg(min_val); 1017 py.arg(min_val); 1018 py.arg(underflow); 1019 py.arg(vec); 1020 py.arg(overflow); 1021 py.arg(min); 1022 py.arg(max); 1023 py.arg(bucket_size); 1024 py.arg(size); 1025 } 1026 py.end(); 1027} 1028 1029void 1030FormulaDataBase::python(Python &py) const 1031{ 1032 const_cast<FormulaDataBase *>(this)->update(); 1033 1034 py.start("Formula"); 1035 py.qarg(name); 1036 py.qarg(desc); 1037 py.kwarg("binned", binned()); 1038 py.kwarg("precision", precision); 1039 py.kwarg("flags", flags); 1040 if (prereq) 1041 py.qkwarg("prereq", prereq->name); 1042 py.qkwarg("formula", str()); 1043 if (!subnames.empty()) 1044 py.qkwarg("subnames", subnames); 1045 if (!subdescs.empty()) 1046 py.qkwarg("subdescs", subdescs); 1047 py.end(); 1048} 1049 1050void 1051DistDataBase::python(Python &py) const 1052{ 1053 const_cast<DistDataBase *>(this)->update(); 1054 1055 py.start("Dist"); 1056 py.qarg(name); 1057 py.qarg(desc); 1058 py.kwarg("binned", binned()); 1059 py.kwarg("precision", precision); 1060 py.kwarg("flags", flags); 1061 if (prereq) 1062 py.qkwarg("prereq", prereq->name); 1063 data.python(py, "dist"); 1064 py.end(); 1065} 1066 1067void 1068VectorDistDataBase::python(Python &py) const 1069{ 1070 const_cast<VectorDistDataBase *>(this)->update(); 1071 1072 py.start("VectorDist"); 1073 py.qarg(name); 1074 py.qarg(desc); 1075 py.kwarg("binned", binned()); 1076 py.kwarg("precision", precision); 1077 py.kwarg("flags", flags); 1078 if (prereq) 1079 py.qkwarg("prereq", prereq->name); 1080 if (!subnames.empty()) 1081 py.qkwarg("subnames", subnames); 1082 if (!subdescs.empty()) 1083 py.qkwarg("subdescs", subdescs); 1084 1085 py.tuple("dist"); 1086 typedef std::vector<DistDataData>::const_iterator iter; 1087 iter i = data.begin(); 1088 iter end = data.end(); 1089 while (i != end) { 1090 i->python(py, ""); 1091 ++i; 1092 } 1093 py.endTuple(); 1094 py.end(); 1095} 1096 1097void 1098Vector2dDataBase::python(Python &py) const 1099{ 1100 const_cast<Vector2dDataBase *>(this)->update(); 1101 1102 py.start("Vector2d"); 1103 py.qarg(name); 1104 py.qarg(desc); 1105 py.kwarg("binned", binned()); 1106 py.kwarg("precision", precision); 1107 py.kwarg("flags", flags); 1108 if (prereq) 1109 py.qkwarg("prereq", prereq->name); 1110 1111 py.kwarg("value", vec); 1112 if (!subnames.empty()) 1113 py.qkwarg("subnames", subnames); 1114 if (!subdescs.empty()) 1115 py.qkwarg("subdescs", subdescs); 1116 if (!y_subnames.empty()) 1117 py.qkwarg("ysubnames", y_subnames); 1118 1119 py.kwarg("x", x); 1120 py.kwarg("y", y); 1121 py.end(); 1122} 1123 1124void 1125FormulaBase::val(rvec_t &vec) const 1126{ 1127 vec = root->val(); 1128} 1129 1130result_t 1131FormulaBase::total() const 1132{ 1133 return root->total(); 1134} 1135 1136size_t 1137FormulaBase::size() const 1138{ 1139 if (!root) 1140 return 0; 1141 else 1142 return root->size(); 1143} 1144 1145bool 1146FormulaBase::binned() const 1147{ 1148 return root && root->binned(); 1149} 1150 1151void 1152FormulaBase::reset() 1153{ 1154} 1155 1156bool 1157FormulaBase::zero() const 1158{ 1159 rvec_t vec; 1160 val(vec); 1161 for (int i = 0; i < vec.size(); ++i) 1162 if (vec[i] != 0.0) 1163 return false; 1164 return true; 1165} 1166 1167void 1168FormulaBase::update(StatData *) 1169{ 1170} 1171 1172string 1173FormulaBase::str() const 1174{ 1175 return root ? root->str() : ""; 1176} 1177 1178Formula::Formula() 1179{ 1180 setInit(); 1181} 1182 1183Formula::Formula(Temp r) 1184{ 1185 root = r; 1186 assert(size()); 1187} 1188 1189const Formula & 1190Formula::operator=(Temp r) 1191{ 1192 assert(!root && "Can't change formulas"); 1193 root = r; 1194 assert(size()); 1195 return *this; 1196} 1197 1198const Formula & 1199Formula::operator+=(Temp r) 1200{ 1201 if (root) 1202 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); 1203 else 1204 root = r; 1205 assert(size()); 1206 return *this; 1207} 1208 1209MainBin::MainBin(const string &name) 1210 : _name(name), mem(NULL), memsize(-1) 1211{ 1212 Database::StatDB().regBin(this, name); 1213} 1214 1215MainBin::~MainBin() 1216{ 1217 if (mem) 1218 delete [] mem; 1219} 1220 1221char * 1222MainBin::memory(off_t off) 1223{ 1224 if (memsize == -1) 1225 memsize = CeilPow2((size_t) offset()); 1226 1227 if (!mem) { 1228 mem = new char[memsize]; 1229 memset(mem, 0, memsize); 1230 } 1231 1232 assert(offset() <= size()); 1233 return mem + off; 1234} 1235 1236void 1237check() 1238{ 1239 Database::StatDB().check(); 1240} 1241 1242void 1243dump(ostream &stream, const string &name, DisplayMode mode) 1244{ 1245 Database::StatDB().dump(stream, name, mode); 1246} 1247 1248CallbackQueue resetQueue; 1249 1250void 1251registerResetCallback(Callback *cb) 1252{ 1253 resetQueue.add(cb); 1254} 1255 1256void 1257reset() 1258{ 1259 Database::StatDB().reset(); 1260 resetQueue.process(); 1261} 1262 1263} // namespace Statistics 1264