/* Copyright (C) 2005 Ricardo Pescuma Domenecci This is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this file; see the file license.txt. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Disable "...truncated to '255' characters in the debug information" warnings #pragma warning(disable: 4786) #include "mir_profiler.h" #include "mir_log.h" #include MProfiler::Block MProfiler::root; MProfiler::Block * MProfiler::current = &MProfiler::root; MProfiler::Block::Block() { parent = NULL; memset(&total, 0, sizeof(total)); started = false; } MProfiler::Block::~Block() { Reset(); } void MProfiler::Block::Reset() { for(std::map::iterator it = children.begin(); it != children.end(); ++it) delete it->second; children.clear(); memset(&total, 0, sizeof(total)); started = false; } void MProfiler::Block::Start() { if (started) return; QueryPerformanceCounter(&start); last_step = start; started = true; } void MProfiler::Block::Step(const char *name) { if (!started) return; LARGE_INTEGER end; QueryPerformanceCounter(&end); GetChild(name)->total.QuadPart += end.QuadPart - last_step.QuadPart; last_step = end; } void MProfiler::Block::Stop() { if (!started) return; LARGE_INTEGER end; QueryPerformanceCounter(&end); total.QuadPart += end.QuadPart - start.QuadPart; started = false; } double MProfiler::Block::GetTimeMS() const { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); return total.QuadPart * 1000. / frequency.QuadPart; } MProfiler::Block * MProfiler::Block::GetChild(const char *name) { MProfiler::Block *ret = children[name]; if (ret == NULL) { ret = new MProfiler::Block(); ret->name = name; ret->parent = this; children[name] = ret; } return ret; } void MProfiler::Reset() { root.Reset(); } void MProfiler::Start(const char *name) { current = current->GetChild(name); current->Start(); } void MProfiler::Step(const char *name) { current->Step(name); } void MProfiler::End() { current->Stop(); if (current->parent != NULL) { current = current->parent; QueryPerformanceCounter(¤t->last_step); } } void MProfiler::Dump(const char *module) { Dump(module, "", &root, -1, -1); } void MProfiler::Dump(const char *module, std::string prefix, Block *block, double parent, double total) { for(std::map::iterator it = block->children.begin(); it != block->children.end(); ++it) { Block *child = it->second; double elapsed = child->GetTimeMS(); if (total > 0) { mlog(module, "Profiler", "%s%-20s\t%5.1lf\t[%3.0lf%%]\t[%3.0lf%%]", prefix.c_str(), it->first.c_str(), elapsed, elapsed / parent * 100, elapsed / total * 100); } else { mlog(module, "Profiler", "%s%-20s\t%5.1lf", prefix.c_str(), it->first.c_str(), elapsed); } Dump(module, prefix + " ", child, elapsed, total > 0 ? total : elapsed); } }