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