// // Urho3D Engine // Copyright (c) 2008-2011 Lasse Öörni // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #include "Precompiled.h" #include "Exception.h" #include "MathDefs.h" #include "Profiler.h" #include #include #include #include #include "DebugNew.h" Profiler* Profiler::sInstance = 0; Profiler::Profiler() : mRoot(0), mCurrent(0), mAccumulatedFrames(0), mTotalFrames(0) { if (sInstance) EXCEPTION("Profiler already exists"); initHiresTimer(); mRoot = new ProfilerBlock(0, "Root"); mCurrent = mRoot; sInstance = this; } Profiler::~Profiler() { delete mRoot; mRoot = 0; mCurrent = 0; if (sInstance == this) sInstance = 0; } void Profiler::beginFrame() { mCurrent = mRoot; mAccumulatedFrames++; mTotalFrames++; } void Profiler::endFrame() { mRoot->endFrame(); } void Profiler::clearAccumulated() { mRoot->clearAccumulated(); mAccumulatedFrames = 0; } std::string Profiler::getData(bool showUnused, bool showAccumulated, bool showTotal) const { std::string output; if (!showTotal) output.append("Block Count Average Total\n \n"); else output.append("Block Frame average (msec) Accumulated total (sec)\n \n"); getData(mRoot, output, 0, showUnused, showAccumulated, showTotal); return output; } void Profiler::getData(ProfilerBlock* block, std::string& output, unsigned indent, bool showUnused, bool showAccumulated, bool showTotal) const { static const int LINE_MAX_LENGTH = 256; static const int NAME_MAX_LENGTH = 40; char line[LINE_MAX_LENGTH]; char indentedName[LINE_MAX_LENGTH]; unsigned frames = max(mTotalFrames, 1); unsigned accumulatedFrames = max(mAccumulatedFrames, 1); // Do not print the root block as it does not collect any actual data if (block != mRoot) { // Output data in milliseconds float frameTime = block->getFrameTime() / 1000.0f; float accumulatedTime = block->getAccumulatedTime() / 1000.0f; float totalTime = block->getTotalTime() / 1000.0f; unsigned frameCount = block->getFrameCount(); unsigned accumulatedCount = block->getAccumulatedCount(); unsigned totalCount = block->getTotalCount(); float avgFrameTime = 0.0f; float avgAccumulatedTime = 0.0f; float avgTotalTime = 0.0f; if (frameCount) avgFrameTime = frameTime / frameCount; if (accumulatedCount) avgAccumulatedTime = accumulatedTime / accumulatedCount; if (totalCount) avgTotalTime = totalTime / totalCount; if ((showUnused) || (frameCount) || ((showAccumulated) && (accumulatedCount))) { memset(indentedName, ' ', NAME_MAX_LENGTH); indentedName[indent] = 0; strcat(indentedName, block->getName()); indentedName[strlen(indentedName)] = ' '; indentedName[NAME_MAX_LENGTH] = 0; if (!showTotal) { if (!showAccumulated) sprintf(line, "%s %5u %8.3f %8.3f\n", indentedName, frameCount, avgFrameTime, frameTime); else sprintf(line, "%s %5u %8.3f %8.3f\n", indentedName, (unsigned)((float)accumulatedCount / accumulatedFrames + 0.5f), avgAccumulatedTime, accumulatedTime / accumulatedFrames); } else { unsigned avgFrameCount = (unsigned)((float)totalCount / frames + 0.5f); float avgFrameTime = avgTotalTime; float avgFrameTotalTime = totalTime / frames; if (!avgFrameCount) { avgFrameTime = 0.0f; avgFrameTotalTime = 0.0f; } sprintf(line, "%s %5u %8.3f %8.3f %10u %8.3f %8.3f\n", indentedName, avgFrameCount, avgFrameTime, avgFrameTotalTime, totalCount, avgTotalTime / 1000.0f, totalTime / 1000.0); } output.append(std::string(line)); indent++; } } const std::vector& children = block->getChildren(); for (std::vector::const_iterator i = children.begin(); i != children.end(); ++i) getData(*i, output, indent, showUnused, showAccumulated, showTotal); }