Continue to work on the profiler
This commit is contained in:
parent
88e680e8e7
commit
aa9bd2098d
|
@ -10,10 +10,15 @@ SET(LIBRARY_OUTPUT_PATH lib/)
|
||||||
# Options
|
# Options
|
||||||
OPTION(COMPILE_EXAMPLES "Select this if you want to build the examples" OFF)
|
OPTION(COMPILE_EXAMPLES "Select this if you want to build the examples" OFF)
|
||||||
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
|
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
|
||||||
|
OPTION(PROFILING_ENABLED "Select this if you want to compile with enabled profiling" OFF)
|
||||||
|
|
||||||
# Headers
|
# Headers
|
||||||
INCLUDE_DIRECTORIES(src)
|
INCLUDE_DIRECTORIES(src)
|
||||||
|
|
||||||
|
IF (PROFILING_ENABLED)
|
||||||
|
ADD_DEFINITIONS(-DIS_PROFILING_ACTIVE)
|
||||||
|
ENDIF (PROFILING_ENABLED)
|
||||||
|
|
||||||
# Library configuration
|
# Library configuration
|
||||||
file (
|
file (
|
||||||
GLOB_RECURSE
|
GLOB_RECURSE
|
||||||
|
|
|
@ -1 +1,141 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
|
||||||
|
* Copyright (c) 2010-2013 Daniel Chappuis *
|
||||||
|
*********************************************************************************
|
||||||
|
* *
|
||||||
|
* This software is provided 'as-is', without any express or implied warranty. *
|
||||||
|
* In no event will the authors be held liable for any damages arising from the *
|
||||||
|
* use of this software. *
|
||||||
|
* *
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, *
|
||||||
|
* including commercial applications, and to alter it and redistribute it *
|
||||||
|
* freely, subject to the following restrictions: *
|
||||||
|
* *
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||||
|
* that you wrote the original software. If you use this software in a *
|
||||||
|
* product, an acknowledgment in the product documentation would be *
|
||||||
|
* appreciated but is not required. *
|
||||||
|
* *
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||||
|
* misrepresented as being the original software. *
|
||||||
|
* *
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "Profiler.h"
|
||||||
|
|
||||||
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
// Initialization of static variables
|
||||||
|
ProfileNode Profiler::mRootNode("Root", NULL);
|
||||||
|
ProfileNode* Profiler::mCurrentNode = &Profiler::mRootNode;
|
||||||
|
uint Profiler::mFrameCounter = 0;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
ProfileNode::ProfileNode(const char* name, ProfileNode* parentNode)
|
||||||
|
:mName(name), mNbTotalCalls(0), mStartingTime(0), mTotalTime(0),
|
||||||
|
mRecursionCounter(0), mParentNode(parentNode), mChildNode(NULL),
|
||||||
|
mSiblingNode(NULL) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
ProfileNode::~ProfileNode() {
|
||||||
|
|
||||||
|
delete mChildNode;
|
||||||
|
delete mSiblingNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to a sub node with a given name
|
||||||
|
ProfileNode* ProfileNode::findSubNode(const char* name) {
|
||||||
|
|
||||||
|
// Try to find the node among the child nodes
|
||||||
|
ProfileNode* child = mChildNode;
|
||||||
|
while (child != NULL) {
|
||||||
|
if (child->mName == name) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
child = child->mSiblingNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The nose has not been found. Therefore, we create it
|
||||||
|
// and add it to the profiler tree
|
||||||
|
ProfileNode* newNode = new ProfileNode(name, this);
|
||||||
|
newNode->mSiblingNode = child;
|
||||||
|
child = newNode;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we enter the block of code corresponding to this profile node
|
||||||
|
void ProfileNode::enterBlockOfCode() {
|
||||||
|
mNbTotalCalls++;
|
||||||
|
|
||||||
|
// If the current code is not called recursively
|
||||||
|
if (mRecursionCounter == 0) {
|
||||||
|
|
||||||
|
// Get the current system time to initialize the starting time of
|
||||||
|
// the profiling of the current block of code
|
||||||
|
mStartingTime = Timer::getCurrentSystemTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
mRecursionCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we exit the block of code corresponding to this profile node
|
||||||
|
bool ProfileNode::exitBlockOfCode() {
|
||||||
|
mRecursionCounter--;
|
||||||
|
|
||||||
|
if (mRecursionCounter == 0 && mNbTotalCalls != 0) {
|
||||||
|
|
||||||
|
// Get the current system time
|
||||||
|
long double currentTime = Timer::getCurrentSystemTime();
|
||||||
|
|
||||||
|
// Increase the total elasped time in the current block of code
|
||||||
|
mTotalTime += currentTime - mStartingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if the current code is not recursing
|
||||||
|
return (mRecursionCounter == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method called when we want to start profiling a block of code.
|
||||||
|
void Profiler::startProfilingBlock(const char* name) {
|
||||||
|
|
||||||
|
// Look for the node in the tree that corresponds to the block of
|
||||||
|
// code to profile
|
||||||
|
if (name != mCurrentNode->getName()) {
|
||||||
|
mCurrentNode = mCurrentNode->findSubNode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start profile the node
|
||||||
|
mCurrentNode->enterBlockOfCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method called at the end of the scope where the
|
||||||
|
// startProfilingBlock() method has been called.
|
||||||
|
void Profiler::stopProfilingBlock() {
|
||||||
|
|
||||||
|
// Go to the parent node unless if the current block
|
||||||
|
// of code is recursing
|
||||||
|
if (mCurrentNode->exitBlockOfCode()) {
|
||||||
|
mCurrentNode = mCurrentNode->getParentNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an iterator over the profiler tree starting at the root
|
||||||
|
ProfileNodeIterator* Profiler::getIterator() {
|
||||||
|
return new ProfileNodeIterator(&mRootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the report of the profiler in a given output stream
|
||||||
|
void printReport(std::ostream& outputStream) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -26,7 +26,146 @@
|
||||||
#ifndef PROFILER_H
|
#ifndef PROFILER_H
|
||||||
#define PROFILER_H
|
#define PROFILER_H
|
||||||
|
|
||||||
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
|
#include "../configuration.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
/// ReactPhysics3D namespace
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Class ProfileNode
|
||||||
|
/**
|
||||||
|
* It represents a profile sample in the profiler tree.
|
||||||
|
*/
|
||||||
|
class ProfileNode {
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
/// Name of the node
|
||||||
|
const char* mName;
|
||||||
|
|
||||||
|
/// Total number of calls of this node
|
||||||
|
uint mNbTotalCalls;
|
||||||
|
|
||||||
|
/// Starting time of the sampling of corresponding block of code
|
||||||
|
long double mStartingTime;
|
||||||
|
|
||||||
|
/// Total time spent in the block of code
|
||||||
|
long double mTotalTime;
|
||||||
|
|
||||||
|
/// Recursion counter
|
||||||
|
int mRecursionCounter;
|
||||||
|
|
||||||
|
/// Pointer to the parent node
|
||||||
|
ProfileNode* mParentNode;
|
||||||
|
|
||||||
|
/// Pointer to a child node
|
||||||
|
ProfileNode* mChildNode;
|
||||||
|
|
||||||
|
/// Pointer to a sibling node
|
||||||
|
ProfileNode* mSiblingNode;
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ProfileNode(const char* name, ProfileNode* parentNode);
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
~ProfileNode();
|
||||||
|
|
||||||
|
/// Return a pointer to a sub node
|
||||||
|
ProfileNode* findSubNode(const char* name);
|
||||||
|
|
||||||
|
/// Return a pointer to the parent node
|
||||||
|
ProfileNode* getParentNode();
|
||||||
|
|
||||||
|
/// Return a pointer to a sibling node
|
||||||
|
ProfileNode* getSiblingNode();
|
||||||
|
|
||||||
|
/// Return a pointer to a child node
|
||||||
|
ProfileNode* getChildNode();
|
||||||
|
|
||||||
|
/// Return the name of the node
|
||||||
|
const char* getName();
|
||||||
|
|
||||||
|
/// Return the total number of call of the corresponding block of code
|
||||||
|
uint getNbTotalCalls() const;
|
||||||
|
|
||||||
|
/// Return the total time spent in the block of code
|
||||||
|
long double getTotalTime() const;
|
||||||
|
|
||||||
|
/// Called when we enter the block of code corresponding to this profile node
|
||||||
|
void enterBlockOfCode();
|
||||||
|
|
||||||
|
/// Called when we exit the block of code corresponding to this profile node
|
||||||
|
bool exitBlockOfCode();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class ProfileNodeIterator
|
||||||
|
/**
|
||||||
|
* This class allow us to iterator over the profiler tree.
|
||||||
|
*/
|
||||||
|
class ProfileNodeIterator {
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
/// Current parent node
|
||||||
|
ProfileNode* mCurrentParent;
|
||||||
|
|
||||||
|
/// Current child node
|
||||||
|
ProfileNode* mCurrentChild;
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ProfileNodeIterator(ProfileNode* startingNode);
|
||||||
|
|
||||||
|
/// Go to the first node
|
||||||
|
void first();
|
||||||
|
|
||||||
|
/// Go to the next node
|
||||||
|
void next();
|
||||||
|
|
||||||
|
/// Enter a given child node
|
||||||
|
void enterChild();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class Profiler
|
||||||
|
/**
|
||||||
|
* This is the main class of the profiler. This profiler is based on "Real-Time Hierarchical
|
||||||
|
* Profiling" article from "Game Programming Gems 3" by Greg Hjelstrom and Byon Garrabrant.
|
||||||
|
*/
|
||||||
|
class Profiler {
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
/// Root node of the profiler tree
|
||||||
|
static ProfileNode mRootNode;
|
||||||
|
|
||||||
|
/// Current node in the current execution
|
||||||
|
static ProfileNode* mCurrentNode;
|
||||||
|
|
||||||
|
/// Frame counter
|
||||||
|
static uint mFrameCounter;
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
/// Method called when we want to start profiling a block of code.
|
||||||
|
static void startProfilingBlock(const char *name);
|
||||||
|
|
||||||
|
/// Method called at the end of the scope where the
|
||||||
|
/// startProfilingBlock() method has been called.
|
||||||
|
static void stopProfilingBlock();
|
||||||
|
|
||||||
|
/// Return an iterator over the profiler tree starting at the root
|
||||||
|
static ProfileNodeIterator* getIterator();
|
||||||
|
|
||||||
|
/// Print the report of the profiler in a given output stream
|
||||||
|
static void printReport(std::ostream& outputStream);
|
||||||
|
};
|
||||||
|
|
||||||
// Class ProfileSample
|
// Class ProfileSample
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +181,7 @@ class ProfileSample {
|
||||||
ProfileSample(const char* name) {
|
ProfileSample(const char* name) {
|
||||||
|
|
||||||
// Ask the profiler to start profiling a block of code
|
// Ask the profiler to start profiling a block of code
|
||||||
Profiler::startProfilingBlock();
|
Profiler::startProfilingBlock(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
|
@ -56,32 +195,43 @@ class ProfileSample {
|
||||||
/// Use this macro to start profile a block of code
|
/// Use this macro to start profile a block of code
|
||||||
#define PROFILE(name) ProfileSample profileSample(name)
|
#define PROFILE(name) ProfileSample profileSample(name)
|
||||||
|
|
||||||
// Class ProfileNode
|
/// Return a pointer to the parent node
|
||||||
/**
|
ProfileNode* ProfileNode::getParentNode() {
|
||||||
* Node of the profiler tree
|
return mParentNode;
|
||||||
*/
|
}
|
||||||
class ProfileNode {
|
|
||||||
|
|
||||||
};
|
/// Return a pointer to a sibling node
|
||||||
|
ProfileNode* ProfileNode::getSiblingNode() {
|
||||||
|
return mSiblingNode;
|
||||||
|
}
|
||||||
|
|
||||||
// Class Profiler
|
/// Return a pointer to a child node
|
||||||
/**
|
ProfileNode* ProfileNode::getChildNode() {
|
||||||
* This is the main class of the profiler
|
return mChildNode;
|
||||||
*/
|
}
|
||||||
class Profiler {
|
|
||||||
|
|
||||||
public :
|
/// Return the name of the node
|
||||||
|
const char* ProfileNode::getName() {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
/// Method called when we want to start profiling a block of code.
|
/// Return the total number of call of the corresponding block of code
|
||||||
static void startProfilingBlock() {
|
uint ProfileNode::getNbTotalCalls() const {
|
||||||
|
return mNbTotalCalls;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
/// Return the total time spent in the block of code
|
||||||
|
long double ProfileNode::getTotalTime() const {
|
||||||
|
return mTotalTime;
|
||||||
|
}
|
||||||
|
|
||||||
/// Method called at the end of the scope where the startProfilingBlock() method
|
}
|
||||||
/// has been called.
|
|
||||||
static void stopProfilingBlock() {
|
|
||||||
|
|
||||||
}
|
#else // In profile is not active
|
||||||
};
|
|
||||||
|
// Empty macro in case profiling is not active
|
||||||
|
#define PROFILE(name)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,23 @@ Timer::~Timer() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the current time of the system
|
||||||
|
long double Timer::getCurrentSystemTime() {
|
||||||
|
|
||||||
|
#if defined(WINDOWS_OS)
|
||||||
|
LARGE_INTEGER ticksPerSecond;
|
||||||
|
LARGE_INTEGER ticks;
|
||||||
|
QueryPerformanceFrequency(&ticksPerSecond);
|
||||||
|
QueryPerformanceCounter(&ticks);
|
||||||
|
return (long double(ticks.QuadPart) / long double(ticksPerSecond.QuadPart));
|
||||||
|
#else
|
||||||
|
// Initialize the lastUpdateTime with the current time in seconds
|
||||||
|
timeval timeValue;
|
||||||
|
gettimeofday(&timeValue, NULL);
|
||||||
|
return (timeValue.tv_sec + (timeValue.tv_usec / 1000000.0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ class Timer {
|
||||||
/// True if the timer is running
|
/// True if the timer is running
|
||||||
bool mIsRunning;
|
bool mIsRunning;
|
||||||
|
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Private copy-constructor
|
/// Private copy-constructor
|
||||||
|
@ -98,8 +99,8 @@ class Timer {
|
||||||
/// Set the timestep of the physics engine
|
/// Set the timestep of the physics engine
|
||||||
void setTimeStep(double timeStep);
|
void setTimeStep(double timeStep);
|
||||||
|
|
||||||
/// Return the current time
|
/// Return the current time of the physics engine
|
||||||
long double getTime() const;
|
long double getPhysicsTime() const;
|
||||||
|
|
||||||
/// Start the timer
|
/// Start the timer
|
||||||
void start();
|
void start();
|
||||||
|
@ -121,6 +122,9 @@ class Timer {
|
||||||
|
|
||||||
/// Compute the interpolation factor
|
/// Compute the interpolation factor
|
||||||
decimal computeInterpolationFactor();
|
decimal computeInterpolationFactor();
|
||||||
|
|
||||||
|
/// Return the current time of the system
|
||||||
|
static long double getCurrentSystemTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the timestep of the physics engine
|
// Return the timestep of the physics engine
|
||||||
|
@ -135,7 +139,7 @@ inline void Timer::setTimeStep(double timeStep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the current time
|
// Return the current time
|
||||||
inline long double Timer::getTime() const {
|
inline long double Timer::getPhysicsTime() const {
|
||||||
return mTime;
|
return mTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,18 +152,8 @@ inline bool Timer::getIsRunning() const {
|
||||||
inline void Timer::start() {
|
inline void Timer::start() {
|
||||||
if (!mIsRunning) {
|
if (!mIsRunning) {
|
||||||
|
|
||||||
#if defined(WINDOWS_OS)
|
// Get the current system time
|
||||||
LARGE_INTEGER ticksPerSecond;
|
mLastUpdateTime = getCurrentSystemTime();
|
||||||
LARGE_INTEGER ticks;
|
|
||||||
QueryPerformanceFrequency(&ticksPerSecond);
|
|
||||||
QueryPerformanceCounter(&ticks);
|
|
||||||
mLastUpdateTime = double(ticks.QuadPart) / double(ticksPerSecond.QuadPart);
|
|
||||||
#else
|
|
||||||
// Initialize the lastUpdateTime with the current time in seconds
|
|
||||||
timeval timeValue;
|
|
||||||
gettimeofday(&timeValue, NULL);
|
|
||||||
mLastUpdateTime = timeValue.tv_sec + (timeValue.tv_usec / 1000000.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mAccumulator = 0.0;
|
mAccumulator = 0.0;
|
||||||
mIsRunning = true;
|
mIsRunning = true;
|
||||||
|
@ -168,7 +162,6 @@ inline void Timer::start() {
|
||||||
|
|
||||||
// Stop the timer
|
// Stop the timer
|
||||||
inline void Timer::stop() {
|
inline void Timer::stop() {
|
||||||
std::cout << "Timer stop" << std::endl;
|
|
||||||
mIsRunning = false;
|
mIsRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,20 +188,9 @@ inline decimal Timer::computeInterpolationFactor() {
|
||||||
|
|
||||||
// Compute the time since the last update() call and add it to the accumulator
|
// Compute the time since the last update() call and add it to the accumulator
|
||||||
inline void Timer::update() {
|
inline void Timer::update() {
|
||||||
long double currentTime;
|
|
||||||
|
|
||||||
#if defined(WINDOWS_OS)
|
// Get the current system time
|
||||||
LARGE_INTEGER ticksPerSecond;
|
long double currentTime = getCurrentSystemTime();
|
||||||
LARGE_INTEGER ticks;
|
|
||||||
QueryPerformanceFrequency(&ticksPerSecond);
|
|
||||||
QueryPerformanceCounter(&ticks);
|
|
||||||
currentTime = double(ticks.QuadPart) / double(ticksPerSecond.QuadPart);
|
|
||||||
#else
|
|
||||||
// Compute the current time is seconds
|
|
||||||
timeval timeValue;
|
|
||||||
gettimeofday(&timeValue, NULL);
|
|
||||||
currentTime = timeValue.tv_sec + (timeValue.tv_usec / 1000000.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Compute the delta display time between two display frames
|
// Compute the delta display time between two display frames
|
||||||
mDeltaTime = currentTime - mLastUpdateTime;
|
mDeltaTime = currentTime - mLastUpdateTime;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user