statistics.cc revision 7461:5a07045d0af2
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 * Authors: Nathan Binkert 29 */ 30 31#include <iomanip> 32#include <fstream> 33#include <list> 34#include <map> 35#include <string> 36 37#include "base/callback.hh" 38#include "base/cprintf.hh" 39#include "base/debug.hh" 40#include "base/hostinfo.hh" 41#include "base/misc.hh" 42#include "base/statistics.hh" 43#include "base/str.hh" 44#include "base/time.hh" 45#include "base/trace.hh" 46 47using namespace std; 48 49namespace Stats { 50 51typedef map<const void *, Info *> MapType; 52 53// We wrap these in a function to make sure they're built in time. 54list<Info *> & 55statsList() 56{ 57 static list<Info *> the_list; 58 return the_list; 59} 60 61MapType & 62statsMap() 63{ 64 static MapType the_map; 65 return the_map; 66} 67 68void 69InfoAccess::setInfo(Info *info) 70{ 71 if (statsMap().find(this) != statsMap().end()) 72 panic("shouldn't register stat twice!"); 73 74 statsList().push_back(info); 75 76#ifndef NDEBUG 77 pair<MapType::iterator, bool> result = 78#endif 79 statsMap().insert(make_pair(this, info)); 80 assert(result.second && "this should never fail"); 81 assert(statsMap().find(this) != statsMap().end()); 82} 83 84void 85InfoAccess::setParams(const StorageParams *params) 86{ 87 info()->storageParams = params; 88} 89 90void 91InfoAccess::setInit() 92{ 93 info()->flags.set(init); 94} 95 96Info * 97InfoAccess::info() 98{ 99 MapType::const_iterator i = statsMap().find(this); 100 assert(i != statsMap().end()); 101 return (*i).second; 102} 103 104const Info * 105InfoAccess::info() const 106{ 107 MapType::const_iterator i = statsMap().find(this); 108 assert(i != statsMap().end()); 109 return (*i).second; 110} 111 112StorageParams::~StorageParams() 113{ 114} 115 116typedef map<std::string, Info *> NameMapType; 117NameMapType & 118nameMap() 119{ 120 static NameMapType the_map; 121 return the_map; 122} 123 124int Info::id_count = 0; 125 126int debug_break_id = -1; 127 128Info::Info() 129 : flags(none), precision(-1), prereq(0), storageParams(NULL) 130{ 131 id = id_count++; 132 if (debug_break_id >= 0 and debug_break_id == id) 133 debug_break(); 134} 135 136Info::~Info() 137{ 138} 139 140void 141Info::setName(const string &name) 142{ 143 pair<NameMapType::iterator, bool> p = 144 nameMap().insert(make_pair(name, this)); 145 146 Info *other = p.first->second; 147 bool result = p.second; 148 149 if (!result) { 150 // using other->name instead of just name to avoid a compiler 151 // warning. They should be the same. 152 panic("same statistic name used twice! name=%s\n", other->name); 153 } 154 155 this->name = name; 156} 157 158bool 159Info::less(Info *stat1, Info *stat2) 160{ 161 const string &name1 = stat1->name; 162 const string &name2 = stat2->name; 163 164 vector<string> v1; 165 vector<string> v2; 166 167 tokenize(v1, name1, '.'); 168 tokenize(v2, name2, '.'); 169 170 size_type last = min(v1.size(), v2.size()) - 1; 171 for (off_type i = 0; i < last; ++i) 172 if (v1[i] != v2[i]) 173 return v1[i] < v2[i]; 174 175 // Special compare for last element. 176 if (v1[last] == v2[last]) 177 return v1.size() < v2.size(); 178 else 179 return v1[last] < v2[last]; 180 181 return false; 182} 183 184bool 185Info::baseCheck() const 186{ 187 if (!(flags & Stats::init)) { 188#ifdef DEBUG 189 cprintf("this is stat number %d\n", id); 190#endif 191 panic("Not all stats have been initialized"); 192 return false; 193 } 194 195 if ((flags & print) && name.empty()) { 196 panic("all printable stats must be named"); 197 return false; 198 } 199 200 return true; 201} 202 203void 204Info::enable() 205{ 206} 207 208void 209VectorInfo::enable() 210{ 211 size_type s = size(); 212 if (subnames.size() < s) 213 subnames.resize(s); 214 if (subdescs.size() < s) 215 subdescs.resize(s); 216} 217 218void 219VectorDistInfo::enable() 220{ 221 size_type s = size(); 222 if (subnames.size() < s) 223 subnames.resize(s); 224 if (subdescs.size() < s) 225 subdescs.resize(s); 226} 227 228void 229Vector2dInfo::enable() 230{ 231 if (subnames.size() < x) 232 subnames.resize(x); 233 if (subdescs.size() < x) 234 subdescs.resize(x); 235 if (y_subnames.size() < y) 236 y_subnames.resize(y); 237} 238 239Formula::Formula() 240{ 241} 242 243Formula::Formula(Temp r) 244{ 245 root = r; 246 setInit(); 247 assert(size()); 248} 249 250const Formula & 251Formula::operator=(Temp r) 252{ 253 assert(!root && "Can't change formulas"); 254 root = r; 255 setInit(); 256 assert(size()); 257 return *this; 258} 259 260const Formula & 261Formula::operator+=(Temp r) 262{ 263 if (root) 264 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 265 else { 266 root = r; 267 setInit(); 268 } 269 270 assert(size()); 271 return *this; 272} 273 274void 275Formula::result(VResult &vec) const 276{ 277 if (root) 278 vec = root->result(); 279} 280 281Result 282Formula::total() const 283{ 284 return root ? root->total() : 0.0; 285} 286 287size_type 288Formula::size() const 289{ 290 if (!root) 291 return 0; 292 else 293 return root->size(); 294} 295 296void 297Formula::reset() 298{ 299} 300 301bool 302Formula::zero() const 303{ 304 VResult vec; 305 result(vec); 306 for (VResult::size_type i = 0; i < vec.size(); ++i) 307 if (vec[i] != 0.0) 308 return false; 309 return true; 310} 311 312string 313Formula::str() const 314{ 315 return root ? root->str() : ""; 316} 317 318void 319enable() 320{ 321 typedef list<Info *>::iterator iter_t; 322 323 iter_t i, end = statsList().end(); 324 for (i = statsList().begin(); i != end; ++i) { 325 Info *info = *i; 326 assert(info); 327 if (!info->check() || !info->baseCheck()) 328 panic("stat check failed for '%s' %d\n", info->name, info->id); 329 } 330 331 off_t j = 0; 332 for (i = statsList().begin(); i != end; ++i) { 333 Info *info = *i; 334 if (!(info->flags & print)) 335 info->name = "__Stat" + to_string(j++); 336 } 337 338 statsList().sort(Info::less); 339 340 for (i = statsList().begin(); i != end; ++i) { 341 Info *info = *i; 342 info->enable(); 343 } 344} 345 346void 347prepare() 348{ 349 list<Info *>::iterator i = statsList().begin(); 350 list<Info *>::iterator end = statsList().end(); 351 while (i != end) { 352 Info *info = *i; 353 info->prepare(); 354 ++i; 355 } 356} 357 358CallbackQueue resetQueue; 359 360void 361reset() 362{ 363 list<Info *>::iterator i = statsList().begin(); 364 list<Info *>::iterator end = statsList().end(); 365 while (i != end) { 366 Info *info = *i; 367 info->reset(); 368 ++i; 369 } 370 371 resetQueue.process(); 372} 373 374void 375registerResetCallback(Callback *cb) 376{ 377 resetQueue.add(cb); 378} 379 380/* namespace Stats */ } 381