add ability to save simulation stats to file

This commit is contained in:
Andrew Meadows 2017-12-07 13:08:34 -08:00
parent fcff9d7e36
commit 4540e9e483
2 changed files with 83 additions and 34 deletions

View file

@ -10,8 +10,11 @@
// //
#include <PhysicsCollisionGroups.h> #include <PhysicsCollisionGroups.h>
#include <functional> #include <functional>
#include <QFile>
#include <PerfStat.h> #include <PerfStat.h>
#include "CharacterController.h" #include "CharacterController.h"
@ -331,58 +334,103 @@ void PhysicsEngine::stepSimulation() {
class CProfileOperator { class CProfileOperator {
public: public:
CProfileOperator(QString context) : _context(context) { CProfileOperator() {}
}; void recurse(CProfileIterator* itr, QString context) {
virtual void process(CProfileIterator*) const = 0; // The context string will get too long if we accumulate it properly
protected: //QString newContext = context + QString("/") + itr->Get_Current_Parent_Name();
QString _context; // so we use this four-character indentation
QString newContext = context + QString(".../");
process(itr, newContext);
// count the children
int32_t numChildren = 0;
itr->First();
while (!itr->Is_Done()) {
itr->Next();
++numChildren;
}
// recurse the children
if (numChildren > 0) {
// recurse the children
for (int32_t i = 0; i < numChildren; ++i) {
itr->Enter_Child(i);
recurse(itr, newContext);
}
}
// retreat back to parent
itr->Enter_Parent();
}
virtual void process(CProfileIterator*, QString context) = 0;
}; };
class PhysicsStatsHarvester : public CProfileOperator { class StatsHarvester : public CProfileOperator {
public: public:
PhysicsStatsHarvester() : CProfileOperator("...") {} StatsHarvester() {}
void process(CProfileIterator* itr) const override { void process(CProfileIterator* itr, QString context) override {
QString name = _context + QString("/") + QString(itr->Get_Current_Name()); QString name = context + itr->Get_Current_Parent_Name();
uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * itr->Get_Current_Total_Time()); uint64_t time = (uint64_t)((btScalar)MSECS_PER_SECOND * itr->Get_Current_Parent_Total_Time());
PerformanceTimer::addTimerRecord(name, time); PerformanceTimer::addTimerRecord(name, time);
}; };
}; };
void recurseOpOnPerformanceStats(const CProfileOperator& op, CProfileIterator* profileIterator) { class StatsWriter : public CProfileOperator {
// get the stats for the children public:
int32_t numChildren = 0; StatsWriter(QString filename) : _file(filename) {
profileIterator->First(); _file.open(QFile::WriteOnly);
while (!profileIterator->Is_Done()) { if (_file.error() != QFileDevice::NoError) {
op.process(profileIterator); qCDebug(physics) << "unable to open file " << _file.fileName() << " to save stepSimulation() stats";
profileIterator->Next(); }
++numChildren;
} }
// recurse the children ~StatsWriter() {
for (int32_t i = 0; i < numChildren; ++i) { _file.close();
profileIterator->Enter_Child(i);
recurseOpOnPerformanceStats(op, profileIterator);
} }
// retreat back to parent void process(CProfileIterator* itr, QString context) override {
profileIterator->Enter_Parent(); QString name = context + itr->Get_Current_Parent_Name();
} float time = (btScalar)MSECS_PER_SECOND * itr->Get_Current_Parent_Total_Time();
if (_file.error() == QFileDevice::NoError) {
QTextStream s(&_file);
s << name << " = " << time << "\n";
}
}
protected:
QFile _file;
};
void PhysicsEngine::harvestPerformanceStats() { void PhysicsEngine::harvestPerformanceStats() {
// unfortunately the full context names get too long for our stats presentation format // unfortunately the full context names get too long for our stats presentation format
//QString contextName = PerformanceTimer::getContextName(); // TODO: how to show full context name? //QString contextName = PerformanceTimer::getContextName(); // TODO: how to show full context name?
QString contextName("..."); QString contextName("...");
CProfileIterator* profileIterator = CProfileManager::Get_Iterator(); CProfileIterator* itr = CProfileManager::Get_Iterator();
if (profileIterator) { if (itr) {
// hunt for stepSimulation context // hunt for stepSimulation context
profileIterator->First(); itr->First();
for (int32_t childIndex = 0; !profileIterator->Is_Done(); ++childIndex) { for (int32_t childIndex = 0; !itr->Is_Done(); ++childIndex) {
if (QString(profileIterator->Get_Current_Name()) == "stepSimulation") { if (QString(itr->Get_Current_Name()) == "stepSimulation") {
profileIterator->Enter_Child(childIndex); itr->Enter_Child(childIndex);
PhysicsStatsHarvester harvester; StatsHarvester harvester;
harvester.process(profileIterator); harvester.recurse(itr, "bt");
break; break;
} }
profileIterator->Next(); itr->Next();
}
}
}
void PhysicsEngine::printPerformanceStatsToFile(const QString& filename) {
CProfileIterator* itr = CProfileManager::Get_Iterator();
if (itr) {
// hunt for stepSimulation context
itr->First();
for (int32_t childIndex = 0; !itr->Is_Done(); ++childIndex) {
if (QString(itr->Get_Current_Name()) == "stepSimulation") {
itr->Enter_Child(childIndex);
StatsWriter writer(filename);
writer.recurse(itr, "");
break;
}
itr->Next();
} }
} }
} }

View file

@ -62,6 +62,7 @@ public:
void stepSimulation(); void stepSimulation();
void harvestPerformanceStats(); void harvestPerformanceStats();
void printPerformanceStatsToFile(const QString& filename);
void updateContactMap(); void updateContactMap();
bool hasOutgoingChanges() const { return _hasOutgoingChanges; } bool hasOutgoingChanges() const { return _hasOutgoingChanges; }