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