statistics.cc revision 2343
1/* 2 * Copyright (c) 2003-2005 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 <fstream> 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/hostinfo.hh" 39#include "base/misc.hh" 40#include "base/statistics.hh" 41#include "base/str.hh" 42#include "base/time.hh" 43#include "base/trace.hh" 44#include "base/stats/statdb.hh" 45 46using namespace std; 47 48namespace Stats { 49 50StatData * 51DataAccess::find() const 52{ 53 return Database::find(const_cast<void *>((const void *)this)); 54} 55 56const StatData * 57getStatData(const void *stat) 58{ 59 return Database::find(const_cast<void *>(stat)); 60} 61 62void 63DataAccess::map(StatData *data) 64{ 65 Database::regStat(this, data); 66} 67 68StatData * 69DataAccess::statData() 70{ 71 StatData *ptr = find(); 72 assert(ptr); 73 return ptr; 74} 75 76const StatData * 77DataAccess::statData() const 78{ 79 const StatData *ptr = find(); 80 assert(ptr); 81 return ptr; 82} 83 84void 85DataAccess::setInit() 86{ 87 statData()->flags |= init; 88} 89 90void 91DataAccess::setPrint() 92{ 93 Database::regPrint(this); 94} 95 96StatData::StatData() 97 : flags(none), precision(-1), prereq(0) 98{ 99 static int count = 0; 100 id = count++; 101} 102 103StatData::~StatData() 104{ 105} 106 107bool 108StatData::less(StatData *stat1, StatData *stat2) 109{ 110 const string &name1 = stat1->name; 111 const string &name2 = stat2->name; 112 113 vector<string> v1; 114 vector<string> v2; 115 116 tokenize(v1, name1, '.'); 117 tokenize(v2, name2, '.'); 118 119 int last = min(v1.size(), v2.size()) - 1; 120 for (int i = 0; i < last; ++i) 121 if (v1[i] != v2[i]) 122 return v1[i] < v2[i]; 123 124 // Special compare for last element. 125 if (v1[last] == v2[last]) 126 return v1.size() < v2.size(); 127 else 128 return v1[last] < v2[last]; 129 130 return false; 131} 132 133bool 134StatData::baseCheck() const 135{ 136 if (!(flags & init)) { 137#ifdef DEBUG 138 cprintf("this is stat number %d\n", id); 139#endif 140 panic("Not all stats have been initialized"); 141 return false; 142 } 143 144 if ((flags & print) && name.empty()) { 145 panic("all printable stats must be named"); 146 return false; 147 } 148 149 return true; 150} 151 152 153void 154FormulaBase::result(VResult &vec) const 155{ 156 if (root) 157 vec = root->result(); 158} 159 160Result 161FormulaBase::total() const 162{ 163 return root ? root->total() : 0.0; 164} 165 166size_t 167FormulaBase::size() const 168{ 169 if (!root) 170 return 0; 171 else 172 return root->size(); 173} 174 175void 176FormulaBase::reset() 177{ 178} 179 180bool 181FormulaBase::zero() const 182{ 183 VResult vec; 184 result(vec); 185 for (int i = 0; i < vec.size(); ++i) 186 if (vec[i] != 0.0) 187 return false; 188 return true; 189} 190 191void 192FormulaBase::update(StatData *) 193{ 194} 195 196string 197FormulaBase::str() const 198{ 199 return root ? root->str() : ""; 200} 201 202Formula::Formula() 203{ 204 setInit(); 205} 206 207Formula::Formula(Temp r) 208{ 209 root = r; 210 assert(size()); 211} 212 213const Formula & 214Formula::operator=(Temp r) 215{ 216 assert(!root && "Can't change formulas"); 217 root = r; 218 assert(size()); 219 return *this; 220} 221 222const Formula & 223Formula::operator+=(Temp r) 224{ 225 if (root) 226 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 227 else 228 root = r; 229 assert(size()); 230 return *this; 231} 232 233void 234check() 235{ 236 typedef Database::stat_list_t::iterator iter_t; 237 238 iter_t i, end = Database::stats().end(); 239 for (i = Database::stats().begin(); i != end; ++i) { 240 StatData *data = *i; 241 assert(data); 242 if (!data->check() || !data->baseCheck()) 243 panic("stat check failed for %s\n", data->name); 244 } 245 246 int j = 0; 247 for (i = Database::stats().begin(); i != end; ++i) { 248 StatData *data = *i; 249 if (!(data->flags & print)) 250 data->name = "__Stat" + to_string(j++); 251 } 252 253 Database::stats().sort(StatData::less); 254 255 if (i == end) 256 return; 257 258 iter_t last = i; 259 ++i; 260 261 for (i = Database::stats().begin(); i != end; ++i) { 262 if ((*i)->name == (*last)->name) 263 panic("same name used twice! name=%s\n", (*i)->name); 264 265 last = i; 266 } 267} 268 269CallbackQueue resetQueue; 270 271void 272reset() 273{ 274 Database::stat_list_t::iterator i = Database::stats().begin(); 275 Database::stat_list_t::iterator end = Database::stats().end(); 276 while (i != end) { 277 StatData *data = *i; 278 data->reset(); 279 ++i; 280 } 281 282 resetQueue.process(); 283} 284 285void 286registerResetCallback(Callback *cb) 287{ 288 resetQueue.add(cb); 289} 290 291/* namespace Stats */ } 292