Merge branch 'profiler' into develop
This commit is contained in:
commit
9aed0ecd6c
|
@ -10,10 +10,15 @@ SET(LIBRARY_OUTPUT_PATH lib/)
|
|||
# Options
|
||||
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(PROFILING_ENABLED "Select this if you want to compile with enabled profiling" OFF)
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES(src)
|
||||
|
||||
IF (PROFILING_ENABLED)
|
||||
ADD_DEFINITIONS(-DIS_PROFILING_ACTIVE)
|
||||
ENDIF (PROFILING_ENABLED)
|
||||
|
||||
# Library configuration
|
||||
file (
|
||||
GLOB_RECURSE
|
||||
|
|
|
@ -61,6 +61,8 @@ CollisionDetection::~CollisionDetection() {
|
|||
|
||||
// Compute the collision detection
|
||||
void CollisionDetection::computeCollisionDetection() {
|
||||
|
||||
PROFILE("CollisionDetection::computeCollisionDetection()");
|
||||
|
||||
// Compute the broad-phase collision detection
|
||||
computeBroadPhase();
|
||||
|
@ -72,6 +74,8 @@ void CollisionDetection::computeCollisionDetection() {
|
|||
// Compute the broad-phase collision detection
|
||||
void CollisionDetection::computeBroadPhase() {
|
||||
|
||||
PROFILE("CollisionDetection::computeBroadPhase()");
|
||||
|
||||
// Notify the broad-phase algorithm about the bodies that have moved since last frame
|
||||
for (set<CollisionBody*>::iterator it = mWorld->getBodiesBeginIterator();
|
||||
it != mWorld->getBodiesEndIterator(); it++) {
|
||||
|
@ -87,6 +91,9 @@ void CollisionDetection::computeBroadPhase() {
|
|||
|
||||
// Compute the narrow-phase collision detection
|
||||
void CollisionDetection::computeNarrowPhase() {
|
||||
|
||||
PROFILE("CollisionDetection::computeNarrowPhase()");
|
||||
|
||||
map<bodyindexpair, BroadPhasePair*>::iterator it;
|
||||
|
||||
// For each possible collision pair of bodies
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "../mathematics/mathematics.h"
|
||||
#include "Profiler.h"
|
||||
#include "../body/CollisionBody.h"
|
||||
#include "OverlappingPair.h"
|
||||
#include "../collision/CollisionDetection.h"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "ContactSolver.h"
|
||||
#include "DynamicsWorld.h"
|
||||
#include "../body/RigidBody.h"
|
||||
#include "Profiler.h"
|
||||
#include <limits>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
@ -748,6 +749,8 @@ void ContactSolver::solveContactConstraints() {
|
|||
// Solve the constraints
|
||||
void ContactSolver::solve(decimal timeStep) {
|
||||
|
||||
PROFILE("ContactSolver::solve()");
|
||||
|
||||
// Set the current time step
|
||||
mTimeStep = timeStep;
|
||||
|
||||
|
|
|
@ -52,11 +52,28 @@ DynamicsWorld::~DynamicsWorld() {
|
|||
|
||||
// Free the allocated memory for the constrained velocities
|
||||
cleanupConstrainedVelocitiesArray();
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// Print the profiling report
|
||||
Profiler::printReport(std::cout);
|
||||
|
||||
// Destroy the profiler (release the allocated memory)
|
||||
Profiler::destroy();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Update the physics simulation
|
||||
void DynamicsWorld::update() {
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
// Increment the frame counter of the profiler
|
||||
Profiler::incrementFrameCounter();
|
||||
#endif
|
||||
|
||||
PROFILE("DynamicsWorld::update()");
|
||||
|
||||
assert(mTimer.getIsRunning());
|
||||
|
||||
// Compute the time since the last update() call and update the timer
|
||||
|
@ -106,6 +123,9 @@ void DynamicsWorld::update() {
|
|||
|
||||
// Update the position and orientation of the rigid bodies
|
||||
void DynamicsWorld::updateRigidBodiesPositionAndOrientation() {
|
||||
|
||||
PROFILE("DynamicsWorld::updateRigidBodiesPositionAndOrientation()");
|
||||
|
||||
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
|
||||
|
||||
// For each rigid body of the world
|
||||
|
@ -159,6 +179,8 @@ void DynamicsWorld::updateRigidBodiesPositionAndOrientation() {
|
|||
|
||||
// Compute and set the interpolation factor to all bodies
|
||||
void DynamicsWorld::setInterpolationFactorToAllBodies() {
|
||||
|
||||
PROFILE("DynamicsWorld::setInterpolationFactorToAllBodies()");
|
||||
|
||||
// Compute the interpolation factor
|
||||
decimal factor = mTimer.computeInterpolationFactor();
|
||||
|
@ -215,6 +237,8 @@ void DynamicsWorld::cleanupConstrainedVelocitiesArray() {
|
|||
// Apply the gravity force to all bodies of the physics world
|
||||
void DynamicsWorld::applyGravity() {
|
||||
|
||||
PROFILE("DynamicsWorld::applyGravity()");
|
||||
|
||||
// For each body of the physics world
|
||||
set<RigidBody*>::iterator it;
|
||||
for (it = getRigidBodiesBeginIterator(); it != getRigidBodiesEndIterator(); ++it) {
|
||||
|
|
257
src/engine/Profiler.cpp
Normal file
257
src/engine/Profiler.cpp
Normal file
|
@ -0,0 +1,257 @@
|
|||
/********************************************************************************
|
||||
* 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;
|
||||
long double Profiler::mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0;
|
||||
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) {
|
||||
reset();
|
||||
}
|
||||
|
||||
// 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 = mChildNode;
|
||||
mChildNode = 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() * 1000.0;
|
||||
}
|
||||
|
||||
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() * 1000.0;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Reset the profiling of the node
|
||||
void ProfileNode::reset() {
|
||||
mNbTotalCalls = 0;
|
||||
mTotalTime = 0.0;
|
||||
|
||||
// Reset the child node
|
||||
if (mChildNode != NULL) {
|
||||
mChildNode->reset();
|
||||
}
|
||||
|
||||
// Reset the sibling node
|
||||
if (mSiblingNode != NULL) {
|
||||
mSiblingNode->reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the node
|
||||
void ProfileNode::destroy() {
|
||||
delete mChildNode;
|
||||
mChildNode = NULL;
|
||||
delete mSiblingNode;
|
||||
mSiblingNode = NULL;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
ProfileNodeIterator::ProfileNodeIterator(ProfileNode* startingNode)
|
||||
:mCurrentParentNode(startingNode),
|
||||
mCurrentChildNode(mCurrentParentNode->getChildNode()){
|
||||
|
||||
}
|
||||
|
||||
// Enter a given child node
|
||||
void ProfileNodeIterator::enterChild(int index) {
|
||||
mCurrentChildNode = mCurrentParentNode->getChildNode();
|
||||
while ((mCurrentChildNode != NULL) && (index != 0)) {
|
||||
index--;
|
||||
mCurrentChildNode = mCurrentChildNode->getSiblingNode();
|
||||
}
|
||||
|
||||
if (mCurrentChildNode != NULL) {
|
||||
mCurrentParentNode = mCurrentChildNode;
|
||||
mCurrentChildNode = mCurrentParentNode->getChildNode();
|
||||
}
|
||||
}
|
||||
|
||||
// Enter a given parent node
|
||||
void ProfileNodeIterator::enterParent() {
|
||||
if (mCurrentParentNode->getParentNode() != NULL) {
|
||||
mCurrentParentNode = mCurrentParentNode->getParentNode();
|
||||
}
|
||||
mCurrentChildNode = mCurrentParentNode->getChildNode();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the timing data of the profiler (but not the profiler tree structure)
|
||||
void Profiler::reset() {
|
||||
mRootNode.reset();
|
||||
mRootNode.enterBlockOfCode();
|
||||
mFrameCounter = 0;
|
||||
mProfilingStartTime = Timer::getCurrentSystemTime() * 1000.0;
|
||||
}
|
||||
|
||||
// Print the report of the profiler in a given output stream
|
||||
void Profiler::printReport(std::ostream& outputStream) {
|
||||
ProfileNodeIterator* iterator = Profiler::getIterator();
|
||||
|
||||
// Recursively print the report of each node of the profiler tree
|
||||
printRecursiveNodeReport(iterator, 0, outputStream);
|
||||
|
||||
// Destroy the iterator
|
||||
destroyIterator(iterator);
|
||||
}
|
||||
|
||||
// Recursively print the report of a given node of the profiler tree
|
||||
void Profiler::printRecursiveNodeReport(ProfileNodeIterator* iterator,
|
||||
int spacing,
|
||||
std::ostream& outputStream) {
|
||||
iterator->first();
|
||||
|
||||
// If we are at the end of a branch in the profiler tree
|
||||
if (iterator->isEnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long double parentTime = iterator->isRoot() ? getElapsedTimeSinceStart() :
|
||||
iterator->getCurrentParentTotalTime();
|
||||
long double accumulatedTime = 0.0;
|
||||
uint nbFrames = Profiler::getNbFrames();
|
||||
for (int i=0; i<spacing; i++) outputStream << " ";
|
||||
outputStream << "---------------" << std::endl;
|
||||
for (int i=0; i<spacing; i++) outputStream << " ";
|
||||
outputStream << "| Profiling : " << iterator->getCurrentParentName() <<
|
||||
" (total running time : " << parentTime << " ms) ---" << std::endl;
|
||||
long double totalTime = 0.0;
|
||||
|
||||
// Recurse over the children of the current node
|
||||
int nbChildren = 0;
|
||||
for (int i=0; !iterator->isEnd(); i++, iterator->next()) {
|
||||
nbChildren++;
|
||||
long double currentTotalTime = iterator->getCurrentTotalTime();
|
||||
accumulatedTime += currentTotalTime;
|
||||
long double fraction = parentTime > std::numeric_limits<long double>::epsilon() ?
|
||||
(currentTotalTime / parentTime) * 100.0 : 0.0;
|
||||
for (int j=0; j<spacing; j++) outputStream << " ";
|
||||
outputStream << "| " << i << " -- " << iterator->getCurrentName() << " : " <<
|
||||
fraction << " % | " << (currentTotalTime / long double(nbFrames)) <<
|
||||
" ms/frame (" << iterator->getCurrentNbTotalCalls() << " calls)" <<
|
||||
std::endl;
|
||||
totalTime += currentTotalTime;
|
||||
}
|
||||
|
||||
if (parentTime < accumulatedTime) {
|
||||
outputStream << "Something is wrong !" << std::endl;
|
||||
}
|
||||
for (int i=0; i<spacing; i++) outputStream << " ";
|
||||
long double percentage = parentTime > std::numeric_limits<long double>::epsilon() ?
|
||||
((parentTime - accumulatedTime) / parentTime) * 100.0 : 0.0;
|
||||
long double difference = parentTime - accumulatedTime;
|
||||
outputStream << "| Unaccounted : " << difference << " ms (" << percentage << " %)" << std::endl;
|
||||
|
||||
for (int i=0; i<nbChildren; i++){
|
||||
iterator->enterChild(i);
|
||||
printRecursiveNodeReport(iterator, spacing + 3, outputStream);
|
||||
iterator->enterParent();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
390
src/engine/Profiler.h
Normal file
390
src/engine/Profiler.h
Normal file
|
@ -0,0 +1,390 @@
|
|||
/********************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef PROFILER_H
|
||||
#define PROFILER_H
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// 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 :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// 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 :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// 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();
|
||||
|
||||
/// Reset the profiling of the node
|
||||
void reset();
|
||||
|
||||
/// Destroy the node
|
||||
void destroy();
|
||||
};
|
||||
|
||||
// Class ProfileNodeIterator
|
||||
/**
|
||||
* This class allows us to iterator over the profiler tree.
|
||||
*/
|
||||
class ProfileNodeIterator {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Current parent node
|
||||
ProfileNode* mCurrentParentNode;
|
||||
|
||||
/// Current child node
|
||||
ProfileNode* mCurrentChildNode;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// 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(int index);
|
||||
|
||||
/// Enter a given parent node
|
||||
void enterParent();
|
||||
|
||||
/// Return true if we are at the root of the profiler tree
|
||||
bool isRoot();
|
||||
|
||||
/// Return true if we are at the end of a branch of the profiler tree
|
||||
bool isEnd();
|
||||
|
||||
/// Return the name of the current node
|
||||
const char* getCurrentName();
|
||||
|
||||
/// Return the total time of the current node
|
||||
long double getCurrentTotalTime();
|
||||
|
||||
/// Return the total number of calls of the current node
|
||||
uint getCurrentNbTotalCalls();
|
||||
|
||||
/// Return the name of the current parent node
|
||||
const char* getCurrentParentName();
|
||||
|
||||
/// Return the total time of the current parent node
|
||||
long double getCurrentParentTotalTime();
|
||||
|
||||
/// Return the total number of calls of the current parent node
|
||||
uint getCurrentParentNbTotalCalls();
|
||||
};
|
||||
|
||||
// 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 :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Root node of the profiler tree
|
||||
static ProfileNode mRootNode;
|
||||
|
||||
/// Current node in the current execution
|
||||
static ProfileNode* mCurrentNode;
|
||||
|
||||
/// Frame counter
|
||||
static uint mFrameCounter;
|
||||
|
||||
/// Starting profiling time
|
||||
static long double mProfilingStartTime;
|
||||
|
||||
/// Recursively print the report of a given node of the profiler tree
|
||||
static void printRecursiveNodeReport(ProfileNodeIterator* iterator,
|
||||
int spacing,
|
||||
std::ostream& outputStream);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// 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();
|
||||
|
||||
/// Reset the timing data of the profiler (but not the profiler tree structure)
|
||||
static void reset();
|
||||
|
||||
/// Return the number of frames
|
||||
static uint getNbFrames();
|
||||
|
||||
/// Return the elasped time since the start/reset of the profiling
|
||||
static long double getElapsedTimeSinceStart();
|
||||
|
||||
/// Increment the frame counter
|
||||
static void incrementFrameCounter();
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Destroy a previously allocated iterator
|
||||
static void destroyIterator(ProfileNodeIterator* iterator);
|
||||
|
||||
/// Destroy the profiler (release the memory)
|
||||
static void destroy();
|
||||
};
|
||||
|
||||
// Class ProfileSample
|
||||
/**
|
||||
* This class is used to represent a profile sample. It is constructed at the
|
||||
* beginning of a code block we want to profile and destructed at the end of the
|
||||
* scope to profile.
|
||||
*/
|
||||
class ProfileSample {
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ProfileSample(const char* name) {
|
||||
|
||||
// Ask the profiler to start profiling a block of code
|
||||
Profiler::startProfilingBlock(name);
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
~ProfileSample() {
|
||||
|
||||
// Tell the profiler to stop profiling a block of code
|
||||
Profiler::stopProfilingBlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Use this macro to start profile a block of code
|
||||
#define PROFILE(name) ProfileSample profileSample(name)
|
||||
|
||||
// Return true if we are at the root of the profiler tree
|
||||
inline bool ProfileNodeIterator::isRoot() {
|
||||
return (mCurrentParentNode->getParentNode() == NULL);
|
||||
}
|
||||
|
||||
// Return true if we are at the end of a branch of the profiler tree
|
||||
inline bool ProfileNodeIterator::isEnd() {
|
||||
return (mCurrentChildNode == NULL);
|
||||
}
|
||||
|
||||
// Return the name of the current node
|
||||
inline const char* ProfileNodeIterator::getCurrentName() {
|
||||
return mCurrentChildNode->getName();
|
||||
}
|
||||
|
||||
// Return the total time of the current node
|
||||
inline long double ProfileNodeIterator::getCurrentTotalTime() {
|
||||
return mCurrentChildNode->getTotalTime();
|
||||
}
|
||||
|
||||
// Return the total number of calls of the current node
|
||||
inline uint ProfileNodeIterator::getCurrentNbTotalCalls() {
|
||||
return mCurrentChildNode->getNbTotalCalls();
|
||||
}
|
||||
|
||||
// Return the name of the current parent node
|
||||
inline const char* ProfileNodeIterator::getCurrentParentName() {
|
||||
return mCurrentParentNode->getName();
|
||||
}
|
||||
|
||||
// Return the total time of the current parent node
|
||||
inline long double ProfileNodeIterator::getCurrentParentTotalTime() {
|
||||
return mCurrentParentNode->getTotalTime();
|
||||
}
|
||||
|
||||
// Return the total number of calls of the current parent node
|
||||
inline uint ProfileNodeIterator::getCurrentParentNbTotalCalls() {
|
||||
return mCurrentParentNode->getNbTotalCalls();
|
||||
}
|
||||
|
||||
// Go to the first node
|
||||
inline void ProfileNodeIterator::first() {
|
||||
mCurrentChildNode = mCurrentParentNode->getChildNode();
|
||||
}
|
||||
|
||||
// Go to the next node
|
||||
inline void ProfileNodeIterator::next() {
|
||||
mCurrentChildNode = mCurrentChildNode->getSiblingNode();
|
||||
}
|
||||
|
||||
// Return a pointer to the parent node
|
||||
inline ProfileNode* ProfileNode::getParentNode() {
|
||||
return mParentNode;
|
||||
}
|
||||
|
||||
// Return a pointer to a sibling node
|
||||
inline ProfileNode* ProfileNode::getSiblingNode() {
|
||||
return mSiblingNode;
|
||||
}
|
||||
|
||||
// Return a pointer to a child node
|
||||
inline ProfileNode* ProfileNode::getChildNode() {
|
||||
return mChildNode;
|
||||
}
|
||||
|
||||
// Return the name of the node
|
||||
inline const char* ProfileNode::getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
// Return the total number of call of the corresponding block of code
|
||||
inline uint ProfileNode::getNbTotalCalls() const {
|
||||
return mNbTotalCalls;
|
||||
}
|
||||
|
||||
// Return the total time spent in the block of code
|
||||
inline long double ProfileNode::getTotalTime() const {
|
||||
return mTotalTime;
|
||||
}
|
||||
|
||||
// Return the number of frames
|
||||
inline uint Profiler::getNbFrames() {
|
||||
return mFrameCounter;
|
||||
}
|
||||
|
||||
// Return the elasped time since the start/reset of the profiling
|
||||
inline long double Profiler::getElapsedTimeSinceStart() {
|
||||
long double currentTime = Timer::getCurrentSystemTime() * 1000.0;
|
||||
return currentTime - mProfilingStartTime;
|
||||
}
|
||||
|
||||
// Increment the frame counter
|
||||
inline void Profiler::incrementFrameCounter() {
|
||||
mFrameCounter++;
|
||||
}
|
||||
|
||||
// Return an iterator over the profiler tree starting at the root
|
||||
inline ProfileNodeIterator* Profiler::getIterator() {
|
||||
return new ProfileNodeIterator(&mRootNode);
|
||||
}
|
||||
|
||||
// Destroy a previously allocated iterator
|
||||
inline void Profiler::destroyIterator(ProfileNodeIterator* iterator) {
|
||||
delete iterator;
|
||||
}
|
||||
|
||||
// Destroy the profiler (release the memory)
|
||||
inline void Profiler::destroy() {
|
||||
mRootNode.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else // In profile is not active
|
||||
|
||||
// Empty macro in case profiling is not active
|
||||
#define PROFILE(name)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -39,6 +39,23 @@ Timer::~Timer() {
|
|||
|
||||
}
|
||||
|
||||
// Return the current time of the system in seconds
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -98,8 +98,8 @@ class Timer {
|
|||
/// Set the timestep of the physics engine
|
||||
void setTimeStep(double timeStep);
|
||||
|
||||
/// Return the current time
|
||||
long double getTime() const;
|
||||
/// Return the current time of the physics engine
|
||||
long double getPhysicsTime() const;
|
||||
|
||||
/// Start the timer
|
||||
void start();
|
||||
|
@ -121,6 +121,9 @@ class Timer {
|
|||
|
||||
/// Compute the interpolation factor
|
||||
decimal computeInterpolationFactor();
|
||||
|
||||
/// Return the current time of the system in seconds
|
||||
static long double getCurrentSystemTime();
|
||||
};
|
||||
|
||||
// Return the timestep of the physics engine
|
||||
|
@ -135,7 +138,7 @@ inline void Timer::setTimeStep(double timeStep) {
|
|||
}
|
||||
|
||||
// Return the current time
|
||||
inline long double Timer::getTime() const {
|
||||
inline long double Timer::getPhysicsTime() const {
|
||||
return mTime;
|
||||
}
|
||||
|
||||
|
@ -147,19 +150,9 @@ inline bool Timer::getIsRunning() const {
|
|||
// Start the timer
|
||||
inline void Timer::start() {
|
||||
if (!mIsRunning) {
|
||||
|
||||
#if defined(WINDOWS_OS)
|
||||
LARGE_INTEGER ticksPerSecond;
|
||||
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
|
||||
|
||||
// Get the current system time
|
||||
mLastUpdateTime = getCurrentSystemTime();
|
||||
|
||||
mAccumulator = 0.0;
|
||||
mIsRunning = true;
|
||||
|
@ -168,7 +161,6 @@ inline void Timer::start() {
|
|||
|
||||
// Stop the timer
|
||||
inline void Timer::stop() {
|
||||
std::cout << "Timer stop" << std::endl;
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
|
@ -195,20 +187,9 @@ inline decimal Timer::computeInterpolationFactor() {
|
|||
|
||||
// Compute the time since the last update() call and add it to the accumulator
|
||||
inline void Timer::update() {
|
||||
long double currentTime;
|
||||
|
||||
#if defined(WINDOWS_OS)
|
||||
LARGE_INTEGER ticksPerSecond;
|
||||
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
|
||||
|
||||
// Get the current system time
|
||||
long double currentTime = getCurrentSystemTime();
|
||||
|
||||
// Compute the delta display time between two display frames
|
||||
mDeltaTime = currentTime - mLastUpdateTime;
|
||||
|
|
Loading…
Reference in New Issue
Block a user