statistics.cc revision 8986
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 312855Sgabeblack@google.com * All rights reserved. 412855Sgabeblack@google.com * 512855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612855Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112855Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412855Sgabeblack@google.com * this software without specific prior written permission. 1512855Sgabeblack@google.com * 1612855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712855Sgabeblack@google.com * 2812855Sgabeblack@google.com * Authors: Nathan Binkert 2912855Sgabeblack@google.com */ 3012855Sgabeblack@google.com 3112855Sgabeblack@google.com#include <fstream> 3212855Sgabeblack@google.com#include <iomanip> 3312855Sgabeblack@google.com#include <list> 3412855Sgabeblack@google.com#include <map> 3512855Sgabeblack@google.com#include <string> 3612855Sgabeblack@google.com 3712855Sgabeblack@google.com#include "base/callback.hh" 3812855Sgabeblack@google.com#include "base/cprintf.hh" 3912855Sgabeblack@google.com#include "base/debug.hh" 4012855Sgabeblack@google.com#include "base/hostinfo.hh" 4112855Sgabeblack@google.com#include "base/misc.hh" 4212855Sgabeblack@google.com#include "base/statistics.hh" 4312855Sgabeblack@google.com#include "base/str.hh" 4412855Sgabeblack@google.com#include "base/time.hh" 4512855Sgabeblack@google.com#include "base/trace.hh" 4612855Sgabeblack@google.com 4712855Sgabeblack@google.comusing namespace std; 4812855Sgabeblack@google.com 4912855Sgabeblack@google.comnamespace Stats { 5012855Sgabeblack@google.com 5112855Sgabeblack@google.comstd::string Info::separatorString = "::"; 5212855Sgabeblack@google.comtypedef map<const void *, Info *> MapType; 5312855Sgabeblack@google.com 5412855Sgabeblack@google.com// We wrap these in a function to make sure they're built in time. 5512855Sgabeblack@google.comlist<Info *> & 5612855Sgabeblack@google.comstatsList() 5712855Sgabeblack@google.com{ 5812855Sgabeblack@google.com static list<Info *> the_list; 5912855Sgabeblack@google.com return the_list; 6012855Sgabeblack@google.com} 6112855Sgabeblack@google.com 6212855Sgabeblack@google.comMapType & 6312855Sgabeblack@google.comstatsMap() 6412855Sgabeblack@google.com{ 6512855Sgabeblack@google.com static MapType the_map; 6612855Sgabeblack@google.com return the_map; 6712855Sgabeblack@google.com} 6812855Sgabeblack@google.com 6912855Sgabeblack@google.comvoid 7012855Sgabeblack@google.comInfoAccess::setInfo(Info *info) 7112855Sgabeblack@google.com{ 7212855Sgabeblack@google.com if (statsMap().find(this) != statsMap().end()) 7312855Sgabeblack@google.com panic("shouldn't register stat twice!"); 7412855Sgabeblack@google.com 7512855Sgabeblack@google.com statsList().push_back(info); 7612855Sgabeblack@google.com 7712855Sgabeblack@google.com#ifndef NDEBUG 7812855Sgabeblack@google.com pair<MapType::iterator, bool> result = 7912855Sgabeblack@google.com#endif 8012855Sgabeblack@google.com statsMap().insert(make_pair(this, info)); 8112855Sgabeblack@google.com assert(result.second && "this should never fail"); 8212855Sgabeblack@google.com assert(statsMap().find(this) != statsMap().end()); 8312855Sgabeblack@google.com} 8412855Sgabeblack@google.com 8512855Sgabeblack@google.comvoid 8612855Sgabeblack@google.comInfoAccess::setParams(const StorageParams *params) 8712855Sgabeblack@google.com{ 8812855Sgabeblack@google.com info()->storageParams = params; 8912855Sgabeblack@google.com} 9012855Sgabeblack@google.com 9112855Sgabeblack@google.comvoid 9212855Sgabeblack@google.comInfoAccess::setInit() 9312855Sgabeblack@google.com{ 9412855Sgabeblack@google.com info()->flags.set(init); 9512855Sgabeblack@google.com} 9612855Sgabeblack@google.com 9712855Sgabeblack@google.comInfo * 9812855Sgabeblack@google.comInfoAccess::info() 9912855Sgabeblack@google.com{ 10012855Sgabeblack@google.com MapType::const_iterator i = statsMap().find(this); 10112855Sgabeblack@google.com assert(i != statsMap().end()); 10212855Sgabeblack@google.com return (*i).second; 10312855Sgabeblack@google.com} 10412855Sgabeblack@google.com 10512855Sgabeblack@google.comconst Info * 10612855Sgabeblack@google.comInfoAccess::info() const 10712855Sgabeblack@google.com{ 10812855Sgabeblack@google.com MapType::const_iterator i = statsMap().find(this); 10912855Sgabeblack@google.com assert(i != statsMap().end()); 11012855Sgabeblack@google.com return (*i).second; 11112855Sgabeblack@google.com} 11212855Sgabeblack@google.com 11312855Sgabeblack@google.comStorageParams::~StorageParams() 11412855Sgabeblack@google.com{ 11512855Sgabeblack@google.com} 11612855Sgabeblack@google.com 11712855Sgabeblack@google.comtypedef map<std::string, Info *> NameMapType; 11812855Sgabeblack@google.comNameMapType & 11912855Sgabeblack@google.comnameMap() 12012855Sgabeblack@google.com{ 12112855Sgabeblack@google.com static NameMapType the_map; 12212855Sgabeblack@google.com return the_map; 12312855Sgabeblack@google.com} 12412855Sgabeblack@google.com 12512855Sgabeblack@google.comint Info::id_count = 0; 12612855Sgabeblack@google.com 12712855Sgabeblack@google.comint debug_break_id = -1; 12812855Sgabeblack@google.com 12912855Sgabeblack@google.comInfo::Info() 13012855Sgabeblack@google.com : flags(none), precision(-1), prereq(0), storageParams(NULL) 13112855Sgabeblack@google.com{ 13212855Sgabeblack@google.com id = id_count++; 13312855Sgabeblack@google.com if (debug_break_id >= 0 and debug_break_id == id) 13412855Sgabeblack@google.com Debug::breakpoint(); 13512855Sgabeblack@google.com} 13612855Sgabeblack@google.com 13712855Sgabeblack@google.comInfo::~Info() 13812855Sgabeblack@google.com{ 13912855Sgabeblack@google.com} 14012855Sgabeblack@google.com 14112855Sgabeblack@google.combool 14212855Sgabeblack@google.comvalidateStatName(const string &name) 14312855Sgabeblack@google.com{ 14412855Sgabeblack@google.com if (name.empty()) 14512855Sgabeblack@google.com return false; 14612855Sgabeblack@google.com 14712855Sgabeblack@google.com vector<string> vec; 14812855Sgabeblack@google.com tokenize(vec, name, '.'); 14912855Sgabeblack@google.com vector<string>::const_iterator item = vec.begin(); 15012855Sgabeblack@google.com while (item != vec.end()) { 15112855Sgabeblack@google.com if (item->empty()) 15212855Sgabeblack@google.com return false; 15312855Sgabeblack@google.com 15412855Sgabeblack@google.com string::const_iterator c = item->begin(); 15512855Sgabeblack@google.com 15612855Sgabeblack@google.com // The first character is different 15712855Sgabeblack@google.com if (!isalpha(*c) && *c != '_') 15812855Sgabeblack@google.com return false; 15912855Sgabeblack@google.com 16012855Sgabeblack@google.com // The rest of the characters have different rules. 16112855Sgabeblack@google.com while (++c != item->end()) { 16212855Sgabeblack@google.com if (!isalnum(*c) && *c != '_') 16312855Sgabeblack@google.com return false; 16412855Sgabeblack@google.com } 16512855Sgabeblack@google.com 16612855Sgabeblack@google.com ++item; 16712855Sgabeblack@google.com } 16812855Sgabeblack@google.com 16912855Sgabeblack@google.com return true; 170} 171 172void 173Info::setName(const string &name) 174{ 175 if (!validateStatName(name)) 176 panic("invalid stat name '%s'", name); 177 178 pair<NameMapType::iterator, bool> p = 179 nameMap().insert(make_pair(name, this)); 180 181 Info *other = p.first->second; 182 bool result = p.second; 183 184 if (!result) { 185 // using other->name instead of just name to avoid a compiler 186 // warning. They should be the same. 187 panic("same statistic name used twice! name=%s\n", other->name); 188 } 189 190 this->name = name; 191} 192 193bool 194Info::less(Info *stat1, Info *stat2) 195{ 196 const string &name1 = stat1->name; 197 const string &name2 = stat2->name; 198 199 vector<string> v1; 200 vector<string> v2; 201 202 tokenize(v1, name1, '.'); 203 tokenize(v2, name2, '.'); 204 205 size_type last = min(v1.size(), v2.size()) - 1; 206 for (off_type i = 0; i < last; ++i) 207 if (v1[i] != v2[i]) 208 return v1[i] < v2[i]; 209 210 // Special compare for last element. 211 if (v1[last] == v2[last]) 212 return v1.size() < v2.size(); 213 else 214 return v1[last] < v2[last]; 215 216 return false; 217} 218 219bool 220Info::baseCheck() const 221{ 222 if (!(flags & Stats::init)) { 223#ifdef DEBUG 224 cprintf("this is stat number %d\n", id); 225#endif 226 panic("Not all stats have been initialized"); 227 return false; 228 } 229 230 if ((flags & display) && name.empty()) { 231 panic("all printable stats must be named"); 232 return false; 233 } 234 235 return true; 236} 237 238void 239Info::enable() 240{ 241} 242 243void 244VectorInfo::enable() 245{ 246 size_type s = size(); 247 if (subnames.size() < s) 248 subnames.resize(s); 249 if (subdescs.size() < s) 250 subdescs.resize(s); 251} 252 253void 254VectorDistInfo::enable() 255{ 256 size_type s = size(); 257 if (subnames.size() < s) 258 subnames.resize(s); 259 if (subdescs.size() < s) 260 subdescs.resize(s); 261} 262 263void 264Vector2dInfo::enable() 265{ 266 if (subnames.size() < x) 267 subnames.resize(x); 268 if (subdescs.size() < x) 269 subdescs.resize(x); 270 if (y_subnames.size() < y) 271 y_subnames.resize(y); 272} 273 274void 275HistStor::grow_out() 276{ 277 int size = cvec.size(); 278 int zero = size / 2; // round down! 279 int top_half = zero + (size - zero + 1) / 2; // round up! 280 int bottom_half = (size - zero) / 2; // round down! 281 282 // grow down 283 int low_pair = zero - 1; 284 for (int i = zero - 1; i >= bottom_half; i--) { 285 cvec[i] = cvec[low_pair]; 286 if (low_pair - 1 >= 0) 287 cvec[i] += cvec[low_pair - 1]; 288 low_pair -= 2; 289 } 290 assert(low_pair == 0 || low_pair == -1 || low_pair == -2); 291 292 for (int i = bottom_half - 1; i >= 0; i--) 293 cvec[i] = Counter(); 294 295 // grow up 296 int high_pair = zero; 297 for (int i = zero; i < top_half; i++) { 298 cvec[i] = cvec[high_pair]; 299 if (high_pair + 1 < size) 300 cvec[i] += cvec[high_pair + 1]; 301 high_pair += 2; 302 } 303 assert(high_pair == size || high_pair == size + 1); 304 305 for (int i = top_half; i < size; i++) 306 cvec[i] = Counter(); 307 308 max_bucket *= 2; 309 min_bucket *= 2; 310 bucket_size *= 2; 311} 312 313void 314HistStor::grow_convert() 315{ 316 int size = cvec.size(); 317 int half = (size + 1) / 2; // round up! 318 //bool even = (size & 1) == 0; 319 320 int pair = size - 1; 321 for (int i = size - 1; i >= half; --i) { 322 cvec[i] = cvec[pair]; 323 if (pair - 1 >= 0) 324 cvec[i] += cvec[pair - 1]; 325 pair -= 2; 326 } 327 328 for (int i = half - 1; i >= 0; i--) 329 cvec[i] = Counter(); 330 331 min_bucket = -max_bucket;// - (even ? bucket_size : 0); 332 bucket_size *= 2; 333} 334 335void 336HistStor::grow_up() 337{ 338 int size = cvec.size(); 339 int half = (size + 1) / 2; // round up! 340 341 int pair = 0; 342 for (int i = 0; i < half; i++) { 343 cvec[i] = cvec[pair]; 344 if (pair + 1 < size) 345 cvec[i] += cvec[pair + 1]; 346 pair += 2; 347 } 348 assert(pair == size || pair == size + 1); 349 350 for (int i = half; i < size; i++) 351 cvec[i] = Counter(); 352 353 max_bucket *= 2; 354 bucket_size *= 2; 355} 356 357Formula::Formula() 358{ 359} 360 361Formula::Formula(Temp r) 362{ 363 root = r; 364 setInit(); 365 assert(size()); 366} 367 368const Formula & 369Formula::operator=(Temp r) 370{ 371 assert(!root && "Can't change formulas"); 372 root = r; 373 setInit(); 374 assert(size()); 375 return *this; 376} 377 378const Formula & 379Formula::operator+=(Temp r) 380{ 381 if (root) 382 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 383 else { 384 root = r; 385 setInit(); 386 } 387 388 assert(size()); 389 return *this; 390} 391 392void 393Formula::result(VResult &vec) const 394{ 395 if (root) 396 vec = root->result(); 397} 398 399Result 400Formula::total() const 401{ 402 return root ? root->total() : 0.0; 403} 404 405size_type 406Formula::size() const 407{ 408 if (!root) 409 return 0; 410 else 411 return root->size(); 412} 413 414void 415Formula::reset() 416{ 417} 418 419bool 420Formula::zero() const 421{ 422 VResult vec; 423 result(vec); 424 for (VResult::size_type i = 0; i < vec.size(); ++i) 425 if (vec[i] != 0.0) 426 return false; 427 return true; 428} 429 430string 431Formula::str() const 432{ 433 return root ? root->str() : ""; 434} 435 436CallbackQueue resetQueue; 437 438void 439registerResetCallback(Callback *cb) 440{ 441 resetQueue.add(cb); 442} 443 444bool _enabled = false; 445 446bool 447enabled() 448{ 449 return _enabled; 450} 451 452void 453enable() 454{ 455 if (_enabled) 456 fatal("Stats are already enabled"); 457 458 _enabled = true; 459} 460 461} // namespace Stats 462 463void 464debugDumpStats() 465{ 466 Stats::dump(); 467} 468