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