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