f956de82825811a9cd45b4057e165ca42b62cae4
2 * Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
41 #include "statistics.hh"
43 #include "universe.hh"
60 static int total_stats
= 0;
65 // This is a hack to get this parameter from the old stats package.
66 namespace Statistics
{
67 bool PrintDescriptions
= true;
84 vector
<SubData
> *subdata
;
92 : init(false), print(false), subdata(NULL
), precision(-1), flags(none
),
106 Database(const Database
&) {}
109 typedef list
<Stat
*> list_t
;
110 typedef map
<const Stat
*, StatData
*> map_t
;
120 void dump(ostream
&stream
);
122 StatData
*find(const Stat
*stat
);
124 void regStat(Stat
*stat
);
125 StatData
*print(Stat
*stat
);
131 Database::~Database()
135 Database::dump(ostream
&stream
)
137 list_t::iterator i
= printStats
.begin();
138 list_t::iterator end
= printStats
.end();
142 if (stat
->dodisplay())
143 stat
->display(stream
);
149 Database::find(const Stat
*stat
)
151 map_t::const_iterator i
= map
.find(stat
);
162 list_t::iterator i
= allStats
.begin();
163 list_t::iterator end
= allStats
.end();
167 StatData
*data
= find(stat
);
168 if (!data
|| !data
->init
) {
170 cprintf("this is stat number %d\n",(*i
)->number
);
172 panic("Not all stats have been initialized");
176 if (data
->name
.empty())
177 panic("all printable stats must be named");
179 list_t::iterator j
= printStats
.insert(printStats
.end(), *i
);
180 inplace_merge(printStats
.begin(), j
,
181 printStats
.end(), Stat::less
);
189 Database::regStat(Stat
*stat
)
191 if (map
.find(stat
) != map
.end())
192 panic("shouldn't register stat twice!");
194 allStats
.push_back(stat
);
196 StatData
*data
= new StatData
;
197 bool success
= (map
.insert(make_pair(stat
, data
))).second
;
198 assert(map
.find(stat
) != map
.end());
199 assert(success
&& "this should never fail");
203 Stat::less(Stat
*stat1
, Stat
*stat2
)
205 const string
&name1
= stat1
->myname();
206 const string
&name2
= stat2
->myname();
211 tokenize(v1
, name1
, '.');
212 tokenize(v2
, name2
, '.');
214 int last
= min(v1
.size(), v2
.size()) - 1;
215 for (int i
= 0; i
< last
; ++i
)
217 return v1
[i
] < v2
[i
];
219 // Special compare for last element.
220 if (v1
[last
] == v2
[last
])
221 return v1
.size() < v2
.size();
223 return v1
[last
] < v2
[last
];
229 Database::print(Stat
*stat
)
231 StatData
*data
= find(stat
);
249 // This assert can help you find that pesky stat.
250 assert(this != (void *)0xbffff5c0);
254 StatDB().regStat(this);
256 number
= ++total_stats
;
257 cprintf("I'm stat number %d\n",number
);
263 { mydata()->init
= true; }
268 StatData
*data
= StatDB().find(this);
277 StatData
*data
= StatDB().find(this);
284 Stat::mysubdata(int index
) const
290 const StatData
*data
= this->mydata();
291 if (!data
->subdata
|| data
->subdata
->size() <= index
)
294 return &(*data
->subdata
)[index
];
298 Stat::mysubdata_create(int index
)
300 int size
= this->size();
301 assert(index
>= 0 && (size
== 0 || size
> 0 && index
< size
));
303 StatData
*data
= this->mydata();
304 if (!data
->subdata
) {
305 if (!data
->subdata
) {
309 data
->subdata
= new vector
<SubData
>(size
);
311 } else if (data
->subdata
->size() <= index
)
312 data
->subdata
->resize(index
+ 1);
314 SubData
*sd
= &(*data
->subdata
)[index
];
322 { return mydata()->name
; }
325 Stat::mysubname(int index
) const
327 const SubData
*sd
= mysubdata(index
);
328 return sd
? sd
->name
: "";
333 { return mydata()->desc
; }
336 Stat::mysubdesc(int index
) const
338 const SubData
*sd
= mysubdata(index
);
339 return sd
? sd
->desc
: "";
343 Stat::myprecision() const
344 { return mydata()->precision
; }
347 Stat::myflags() const
348 { return mydata()->flags
; }
351 Stat::dodisplay() const
352 { return !mydata()->prereq
|| !mydata()->prereq
->zero(); }
357 StatData
*data
= StatDB().print(this);
358 assert(data
&& data
->init
);
364 Stat::name(const string
&name
)
366 print()->name
= name
;
371 Stat::desc(const string
&desc
)
373 print()->desc
= desc
;
378 Stat::precision(int precision
)
380 print()->precision
= precision
;
385 Stat::flags(FormatFlags flags
)
387 if (flags
& __reserved
)
388 panic("Cannot set reserved flags!\n");
390 print()->flags
|= flags
;
395 Stat::prereq(const Stat
&prereq
)
397 print()->prereq
= &prereq
;
402 Stat::subname(int index
, const string
&name
)
405 mysubdata_create(index
)->name
= name
;
409 Stat::subdesc(int index
, const string
&desc
)
412 mysubdata_create(index
)->desc
= desc
;
417 ScalarStat::zero() const
423 VectorStat::zero() const
425 return val()[0] == 0.0;
429 ValueToString(result_t value
, int precision
)
435 val
.precision(precision
);
436 else if (value
== rint(value
))
439 val
.unsetf(ios::showpoint
);
440 val
.setf(ios::fixed
);
443 #ifndef STAT_DISPLAY_COMPAT
446 val
<< "<err: div-0>";
454 PrintOne(ostream
&stream
, result_t value
,
455 const string
&name
, const string
&desc
, int precision
,
456 FormatFlags flags
, result_t pdf
= NAN
, result_t cdf
= NAN
)
458 if (flags
& nozero
&& value
== 0.0 ||
459 flags
& nonan
&& isnan(value
))
462 stringstream pdfstr
, cdfstr
;
465 ccprintf(pdfstr
, "%.2f%%", pdf
* 100.0);
468 ccprintf(cdfstr
, "%.2f%%", cdf
* 100.0);
470 #ifdef STAT_DISPLAY_COMPAT
471 if (flags
& __substat
) {
472 ccprintf(stream
, "%32s%12s%10s%10s", name
,
473 ValueToString(value
, precision
),
478 ccprintf(stream
, "%-40s%12s%10s%10s", name
,
479 ValueToString(value
, precision
), pdfstr
, cdfstr
);
482 if (PrintDescriptions
) {
484 ccprintf(stream
, " # %s", desc
);
490 ScalarStat::display(ostream
&stream
) const
492 PrintOne(stream
, val(), myname(), mydesc(), myprecision(), myflags());
496 VectorStat::display(ostream
&stream
) const
498 bool have_subname
= false;
499 bool have_subdesc
= false;
500 int size
= this->size();
501 for (int i
= 0; i
< size
; ++i
) {
502 if (!mysubname(i
).empty())
504 if (!mysubdesc(i
).empty())
508 vector
<string
> *subnames
= 0;
509 vector
<string
> *subdescs
= 0;
511 subnames
= new vector
<string
>(size
);
512 for (int i
= 0; i
< size
; ++i
)
513 (*subnames
)[i
] = mysubname(i
);
516 subdescs
= new vector
<string
>(size
);
517 for (int i
= 0; i
< size
; ++i
)
518 (*subdescs
)[i
] = mysubdesc(i
);
521 VectorDisplay(stream
, myname(), subnames
, mydesc(), subdescs
,
522 myprecision(), myflags(), val(), total());
525 #ifndef STAT_DISPLAY_COMPAT
531 #ifndef STAT_DISPLAY_COMPAT
533 VectorDisplay(std::ostream
&stream
,
534 const std::string
&myname
,
535 const std::vector
<std::string
> *mysubnames
,
536 const std::string
&mydesc
,
537 const std::vector
<std::string
> *mysubdescs
,
538 int myprecision
, FormatFlags myflags
,
539 const rvec_t
&vec
, result_t mytotal
)
541 int _size
= vec
.size();
542 result_t _total
= 0.0;
543 result_t _pdf
, _cdf
= 0.0;
545 if (myflags
& (pdf
| cdf
)) {
546 for (int i
= 0; i
< _size
; ++i
) {
552 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
554 for (int i
= 0; i
< _size
; ++i
) {
557 subname
= (*mysubnames
)[i
];
561 subname
= to_string(i
);
564 string name
= myname
+ NAMESEP
+ subname
;
565 if (!(myflags
& pdf
))
566 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
);
568 _pdf
= vec
[i
] / _total
;
570 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
,
576 PrintOne(stream
, mytotal
, myname
+ NAMESEP
+ "total",
577 mydesc
, myprecision
, myflags
);
582 VectorDisplay(std::ostream
&stream
,
583 const std::string
&myname
,
584 const std::vector
<std::string
> *mysubnames
,
585 const std::string
&mydesc
,
586 const std::vector
<std::string
> *mysubdescs
,
587 int myprecision
, FormatFlags myflags
,
588 const rvec_t
&vec
, result_t mytotal
)
590 int _size
= vec
.size();
591 result_t _total
= 0.0;
592 result_t _pdf
, _cdf
= 0.0;
594 if (myflags
& (pdf
| cdf
)) {
595 for (int i
= 0; i
< _size
; ++i
) {
601 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
604 PrintOne(stream
, mytotal
, myname
, mydesc
, myprecision
, myflags
);
606 if (myflags
& dist
) {
607 ccprintf(stream
, "%s.start_dist\n", myname
);
608 for (int i
= 0; i
< _size
; ++i
) {
609 string subname
, subdesc
;
610 subname
= to_string(i
);
612 if (!subname
.empty()) {
613 subname
= (*mysubnames
)[i
];
617 subdesc
= (*mysubdescs
)[i
];
619 if (!(myflags
& (pdf
| cdf
))) {
620 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
621 myflags
| __substat
);
624 _pdf
= vec
[i
] / _total
;
629 if (!(myflags
& cdf
)) {
630 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
631 myflags
| __substat
, _pdf
);
633 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
634 myflags
| __substat
, _pdf
, _cdf
);
638 ccprintf(stream
, "%s.end_dist\n", myname
);
640 for (int i
= 0; i
< _size
; ++i
) {
643 subname
= (*mysubnames
)[i
];
647 subname
= to_string(i
);
650 string name
= myname
+ NAMESEP
+ subname
;
651 if (!(myflags
& pdf
)) {
652 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
656 _pdf
= vec
[i
] / _total
;
661 _pdf
= vec
[i
] / _total
;
663 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
664 myflags
, _pdf
, _cdf
);
672 #ifndef STAT_DISPLAY_COMPAT
674 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
675 int precision
, FormatFlags flags
,
676 result_t min_val
, result_t max_val
,
677 result_t underflow
, result_t overflow
,
678 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
);
680 assert(size
== vec
.size());
682 result_t total
= 0.0;
683 result_t pdf
, cdf
= 0.0;
686 for (int i
= 0; i
< size
; ++i
)
690 pdf
= underflow
/ total
;
693 PrintOne(stream
, underflow
, name
+ NAMESEP
+ "underflow", desc
,
694 precision
, myflags
, pdf
, cdf
);
696 for (int i
= 0; i
< size
; ++i
) {
697 stringstream namestr
;
700 int low
= i
* bucket_size
+ min
;
701 int high
= ::std::min((i
+ 1) * bucket_size
+ min
- 1, max
);
704 namestr
<< "-" << high
;
706 pdf
= vec
[i
] / total
;
708 PrintOne(stream
, vec
[i
], namestr
.str(), desc
, precision
, myflags
,
712 pdf
= overflow
/ total
;
714 PrintOne(stream
, overflow
, name
+ NAMESEP
+ "overflow", desc
,
715 precision
, myflags
, pdf
, cdf
);
716 PrintOne(stream
, total
, name
+ NAMESEP
+ "total", desc
,
721 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
722 int precision
, FormatFlags flags
,
723 result_t min_val
, result_t max_val
,
724 result_t underflow
, result_t overflow
,
725 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
)
727 assert(size
== vec
.size());
730 result_t total
= 0.0;
733 for (int i
= 0; i
< size
; ++i
)
737 ccprintf(stream
, "%-42s", name
+ ".start_dist");
738 if (PrintDescriptions
&& !desc
.empty())
739 ccprintf(stream
, " # %s", desc
);
742 PrintOne(stream
, total
, name
+ ".samples", blank
, precision
, flags
);
743 PrintOne(stream
, min_val
, name
+ ".min_value", blank
, precision
, flags
);
746 PrintOne(stream
, min_val
, name
+ ".underflows", blank
, precision
,
750 result_t _pdf
, _cdf
, mypdf
, mycdf
;
753 for (int i
= 0; i
< size
; ++i
) {
754 if (flags
& nozero
&& vec
[i
] == 0.0 ||
755 flags
& nonan
&& isnan(vec
[i
]))
758 _min
= i
* bucket_size
+ min
;
759 _pdf
= vec
[i
] / total
* 100.0;
762 mypdf
= (flags
& pdf
) ? _pdf
: NAN
;
763 mycdf
= (flags
& cdf
) ? _cdf
: NAN
;
765 PrintOne(stream
, vec
[i
], ValueToString(_min
, 0), blank
, precision
,
766 flags
| __substat
, mypdf
, mycdf
);
770 PrintOne(stream
, overflow
, name
+ ".overflows", blank
, precision
,
772 PrintOne(stream
, max_val
, name
+ ".max_value", blank
, precision
, flags
);
773 ccprintf(stream
, "%s.end_dist\n\n", name
);
778 FancyDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
779 int precision
, FormatFlags flags
, result_t mean
,
782 result_t stdev
= isnan(variance
) ? NAN
: sqrt(variance
);
783 PrintOne(stream
, mean
, name
+ NAMESEP
+ "mean", desc
, precision
, flags
);
784 PrintOne(stream
, stdev
, name
+ NAMESEP
+ "stdev", desc
, precision
, flags
);
787 BinBase::BinBase(size_t size
)
788 : memsize(CeilPow2(size
)), mem(NULL
)
802 mem
= new char[memsize
];
803 memset(mem
, 0, memsize
);
809 } // namespace Detail
814 Detail::StatDB().check();
818 dump(ostream
&stream
)
820 Detail::StatDB().dump(stream
);
823 } // namespace Statistics