statistics.cc revision 433
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 default_mode = 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); 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); 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->print) 239 return; 240 241 data->print = true; 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()->init = true; 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 (!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 (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 int precision; 372 DisplayMode mode; 373 FormatFlags flags; 374 result_t pdf; 375 result_t cdf; 376 377 ScalarPrint() 378 : value(0.0), precision(0), mode(default_mode), flags(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), 403 pdfstr, cdfstr); 404 } else { 405 ccprintf(stream, "%-40s %12s %10s %10s", name, 406 ValueToString(value, mode, precision), pdfstr, cdfstr); 407 } 408 409 if (PrintDescriptions) { 410 if (!desc.empty()) 411 ccprintf(stream, " # %s", desc); 412 } 413 stream << endl; 414} 415 416struct VectorPrint 417{ 418 string name; 419 string desc; 420 vector<string> subnames; 421 vector<string> subdescs; 422 int precision; 423 DisplayMode mode; 424 FormatFlags flags; 425 rvec_t vec; 426 result_t total; 427 428 VectorPrint() 429 : subnames(0), subdescs(0), precision(-1), mode(default_mode), 430 flags(0), total(NAN) 431 {} 432 433 void operator()(ostream &stream) const; 434}; 435 436void 437VectorPrint::operator()(std::ostream &stream) const 438{ 439 int _size = vec.size(); 440 result_t _total = 0.0; 441 442 if (flags & (pdf | cdf)) { 443 for (int i = 0; i < _size; ++i) { 444 _total += vec[i]; 445 } 446 } 447 448 string base = name + ((mode == mode_simplescalar) ? "_" : "::"); 449 450 ScalarPrint print; 451 print.name = name; 452 print.desc = desc; 453 print.precision = precision; 454 print.flags = flags; 455 456 bool havesub = !subnames.empty(); 457 458 if (_size == 1) { 459 print.value = vec[0]; 460 print(stream); 461 } else if (mode == mode_m5) { 462 for (int i = 0; i < _size; ++i) { 463 if (havesub && (i >= subnames.size() || subnames[i].empty())) 464 continue; 465 466 print.name = base + (havesub ? subnames[i] : to_string(i)); 467 print.desc = subdescs.empty() ? desc : subdescs[i]; 468 print.value = vec[i]; 469 470 if (_total && (flags & pdf)) { 471 print.pdf = vec[i] / _total; 472 print.cdf += print.pdf; 473 } 474 475 print(stream); 476 } 477 478 if (flags & ::Statistics::total) { 479 print.name = base + "total"; 480 print.desc = desc; 481 print.value = total; 482 print(stream); 483 } 484 } else { 485 if (flags & ::Statistics::total) { 486 print.value = total; 487 print(stream); 488 } 489 490 result_t _pdf = 0.0; 491 result_t _cdf = 0.0; 492 if (flags & dist) { 493 ccprintf(stream, "%s.start_dist\n", name); 494 for (int i = 0; i < _size; ++i) { 495 print.name = havesub ? subnames[i] : to_string(i); 496 print.desc = subdescs.empty() ? desc : subdescs[i]; 497 print.flags |= __substat; 498 print.value = vec[i]; 499 500 if (_total) { 501 _pdf = vec[i] / _total; 502 _cdf += _pdf; 503 } 504 505 if (flags & pdf) 506 print.pdf = _pdf; 507 if (flags & cdf) 508 print.cdf = _cdf; 509 510 print(stream); 511 } 512 ccprintf(stream, "%s.end_dist\n", name); 513 } else { 514 for (int i = 0; i < _size; ++i) { 515 if (havesub && subnames[i].empty()) 516 continue; 517 518 print.name = base; 519 print.name += havesub ? subnames[i] : to_string(i); 520 print.desc = subdescs.empty() ? desc : subdescs[i]; 521 print.value = vec[i]; 522 523 if (_total) { 524 _pdf = vec[i] / _total; 525 _cdf += _pdf; 526 } else { 527 _pdf = _cdf = NAN; 528 } 529 530 if (flags & pdf) { 531 print.pdf = _pdf; 532 print.cdf = _cdf; 533 } 534 535 print(stream); 536 } 537 } 538 } 539} 540 541struct DistPrint 542{ 543 string name; 544 string desc; 545 int precision; 546 DisplayMode mode; 547 FormatFlags flags; 548 549 result_t min_val; 550 result_t max_val; 551 result_t underflow; 552 result_t overflow; 553 rvec_t vec; 554 result_t sum; 555 result_t squares; 556 result_t samples; 557 558 int min; 559 int max; 560 int bucket_size; 561 int size; 562 bool fancy; 563 564 void operator()(ostream &stream) const; 565}; 566 567void 568DistPrint::operator()(ostream &stream) const 569{ 570 if (fancy) { 571 ScalarPrint print; 572 string base = name + ((mode == mode_m5) ? "::" : "_"); 573 574 print.precision = precision; 575 print.flags = flags; 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.precision = precision; 607 print.mode = mode; 608 print.flags = flags; 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 (mode == mode_m5 && 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) const 727{ 728 ScalarPrint print; 729 print.value = val(); 730 print.name = name; 731 print.desc = desc; 732 print.precision = precision; 733 print.flags = flags; 734 735 print(stream); 736} 737 738void 739VectorDataBase::display(ostream &stream) const 740{ 741 int size = this->size(); 742 const_cast<VectorDataBase *>(this)->update(); 743 744 VectorPrint print; 745 746 print.name = name; 747 print.desc = desc; 748 print.mode = mode; 749 print.flags = flags; 750 print.precision = precision; 751 print.vec = val(); 752 print.total = total(); 753 754 for (int i = 0; i < size; ++i) { 755 if (!subnames[i].empty()) { 756 print.subnames = subnames; 757 print.subnames.resize(size); 758 for (int i = 0; i < size; ++i) { 759 if (!subnames[i].empty() && !subdescs[i].empty()) { 760 print.subdescs = subdescs; 761 print.subdescs.resize(size); 762 break; 763 } 764 } 765 break; 766 } 767 } 768 769 770 print(stream); 771} 772 773void 774Vector2dDataBase::display(ostream &stream) const 775{ 776 const_cast<Vector2dDataBase *>(this)->update(); 777 778 bool havesub = false; 779 VectorPrint print; 780 781 print.subnames = y_subnames; 782 print.mode = mode; 783 print.flags = flags; 784 print.precision = precision; 785 786 if (!subnames.empty()) { 787 for (int i = 0; i < x; ++i) 788 if (!subnames[i].empty()) 789 havesub = true; 790 } 791 792 rvec_t tot_vec(y); 793 result_t super_total = 0.0; 794 for (int i = 0; i < x; ++i) { 795 if (havesub && (i >= subnames.size() || subnames[i].empty())) 796 continue; 797 798 int iy = i * y; 799 rvec_t yvec(y); 800 801 result_t total = 0.0; 802 for (int j = 0; j < y; ++j) { 803 yvec[j] = vec[iy + j]; 804 tot_vec[j] += yvec[j]; 805 total += yvec[j]; 806 super_total += yvec[j]; 807 } 808 809 print.name = name + "_" + (havesub ? subnames[i] : to_string(i)); 810 print.desc = desc; 811 print.vec = yvec; 812 print.total = total; 813 print(stream); 814 } 815 816 if ((flags & ::Statistics::total) && (x > 1)) { 817 print.name = name; 818 print.desc = desc; 819 print.vec = tot_vec; 820 print.total = super_total; 821 print(stream); 822 } 823} 824 825void 826DistDataBase::display(ostream &stream) const 827{ 828 const_cast<DistDataBase *>(this)->update(); 829 830 DistPrint print; 831 832 print.name = name; 833 print.desc = desc; 834 print.precision = precision; 835 print.mode = mode; 836 print.flags = flags; 837 838 print.min_val = data.min_val; 839 print.max_val = data.max_val; 840 print.underflow = data.underflow; 841 print.overflow = data.overflow; 842 print.vec = data.vec; 843 print.sum = data.sum; 844 print.squares = data.squares; 845 print.samples = data.samples; 846 847 print.min = data.min; 848 print.max = data.max; 849 print.bucket_size = data.bucket_size; 850 print.size = data.size; 851 print.fancy = data.fancy; 852 853 print(stream); 854} 855 856void 857VectorDistDataBase::display(ostream &stream) const 858{ 859 const_cast<VectorDistDataBase *>(this)->update(); 860 861 for (int i = 0; i < size(); ++i) { 862 DistPrint print; 863 864 print.name = name + 865 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]); 866 print.desc = subdescs[i].empty() ? desc : subdescs[i]; 867 print.precision = precision; 868 print.mode = mode; 869 print.flags = flags; 870 871 print.min_val = data[i].min_val; 872 print.max_val = data[i].max_val; 873 print.underflow = data[i].underflow; 874 print.overflow = data[i].overflow; 875 print.vec = data[i].vec; 876 print.sum = data[i].sum; 877 print.squares = data[i].squares; 878 print.samples = data[i].samples; 879 880 print.min = data[i].min; 881 print.max = data[i].max; 882 print.bucket_size = data[i].bucket_size; 883 print.size = data[i].size; 884 print.fancy = data[i].fancy; 885 886 print(stream); 887 } 888} 889 890void 891FormulaBase::val(rvec_t &vec) const 892{ 893 vec = root->val(); 894} 895 896result_t 897FormulaBase::total() const 898{ 899 return root->total(); 900} 901 902size_t 903FormulaBase::size() const 904{ 905 if (!root) 906 return 0; 907 else 908 return root->size(); 909} 910 911bool 912FormulaBase::binned() const 913{ 914 return root->binned(); 915} 916 917void 918FormulaBase::reset() 919{ 920} 921 922bool 923FormulaBase::zero() const 924{ 925 rvec_t vec; 926 val(vec); 927 for (int i = 0; i < vec.size(); ++i) 928 if (vec[i] != 0.0) 929 return false; 930 return true; 931} 932 933void 934FormulaBase::update(StatData *) 935{ 936} 937 938Formula::Formula() 939{ 940 setInit(); 941} 942 943Formula::Formula(Temp r) 944{ 945 root = r; 946 assert(size()); 947} 948 949const Formula & 950Formula::operator=(Temp r) 951{ 952 assert(!root && "Can't change formulas"); 953 root = r; 954 assert(size()); 955 return *this; 956} 957 958const Formula & 959Formula::operator+=(Temp r) 960{ 961 if (root) 962 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); 963 else 964 root = r; 965 assert(size()); 966 return *this; 967} 968 969MainBin::MainBin(const string &name) 970 : _name(name), mem(NULL), memsize(-1) 971{ 972 Database::StatDB().regBin(this, name); 973} 974 975MainBin::~MainBin() 976{ 977 if (mem) 978 delete [] mem; 979} 980 981char * 982MainBin::memory(off_t off) 983{ 984 if (memsize == -1) 985 memsize = CeilPow2((size_t) offset()); 986 987 if (!mem) { 988 mem = new char[memsize]; 989 memset(mem, 0, memsize); 990 } 991 992 assert(offset() <= size()); 993 return mem + off; 994} 995 996void 997check() 998{ 999 Database::StatDB().check(); 1000} 1001 1002void 1003dump(ostream &stream, DisplayMode mode) 1004{ 1005 Database::StatDB().dump(stream, mode); 1006} 1007 1008CallbackQueue resetQueue; 1009 1010void 1011registerResetCallback(Callback *cb) 1012{ 1013 resetQueue.add(cb); 1014} 1015 1016void 1017reset() 1018{ 1019 Database::StatDB().reset(); 1020 resetQueue.process(); 1021} 1022 1023} // namespace Statistics 1024