From b9a1faf2848697ade81f426b939f8718b7a95003 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 14:46:39 -0700 Subject: [PATCH] add a new SimpleMovingAverage class, replaces CounterStats --- interface/src/VoxelSystem.cpp | 12 +- interface/src/VoxelSystem.h | 6 +- interface/src/main.cpp | 34 +---- libraries/shared/src/CounterStats.cpp | 142 ------------------- libraries/shared/src/CounterStats.h | 65 --------- libraries/shared/src/SimpleMovingAverage.cpp | 51 +++++++ libraries/shared/src/SimpleMovingAverage.h | 34 +++++ libraries/voxels/src/VoxelTree.cpp | 27 ++-- libraries/voxels/src/VoxelTree.h | 12 +- 9 files changed, 116 insertions(+), 267 deletions(-) delete mode 100644 libraries/shared/src/CounterStats.cpp delete mode 100644 libraries/shared/src/CounterStats.h create mode 100644 libraries/shared/src/SimpleMovingAverage.cpp create mode 100644 libraries/shared/src/SimpleMovingAverage.h diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 412c0aac75..cf88a199d0 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -93,24 +93,24 @@ long int VoxelSystem::getVoxelsCreated() { return tree->voxelsCreated; } -long int VoxelSystem::getVoxelsCreatedRunningAverage() { - return tree->voxelsCreatedStats.getRunningAverage(); +float VoxelSystem::getVoxelsCreatedPerSecondAverage() { + return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); } long int VoxelSystem::getVoxelsColored() { return tree->voxelsColored; } -long int VoxelSystem::getVoxelsColoredRunningAverage() { - return tree->voxelsColoredStats.getRunningAverage(); +float VoxelSystem::getVoxelsColoredPerSecondAverage() { + return tree->voxelsColoredStats.getEventDeltaAverage(); } long int VoxelSystem::getVoxelsBytesRead() { return tree->voxelsBytesRead; } -long int VoxelSystem::getVoxelsBytesReadRunningAverage() { - return tree->voxelsBytesReadStats.getRunningAverage(); +float VoxelSystem::getVoxelsBytesReadAverage() { + return tree->voxelsBytesReadStats.getAverage(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5395ce700a..3ca39d75bf 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -40,9 +40,9 @@ public: long int getVoxelsCreated(); long int getVoxelsColored(); long int getVoxelsBytesRead(); - long int getVoxelsCreatedRunningAverage(); - long int getVoxelsColoredRunningAverage(); - long int getVoxelsBytesReadRunningAverage(); + float getVoxelsCreatedPerSecondAverage(); + float getVoxelsColoredPerSecondAverage(); + float getVoxelsBytesReadAverage(); private: int voxelsRendered; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 4aa20f8b91..4e43381edc 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -74,10 +74,11 @@ #include "Oscilloscope.h" #include "UDPSocket.h" #include "SerialInterface.h" -#include #include #include #include +#include +#include #include "ViewFrustum.h" @@ -235,35 +236,6 @@ void displayStats(void) sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ", FPS, packetsPerSecond, bytesPerSecond, avatarPos.x,avatarPos.y,avatarPos.z); drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); - - std::stringstream voxelStats; - voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered(); - drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedRunningAverage() - << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; - drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredRunningAverage() - << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; - drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead() - << " (" << voxels.getVoxelsBytesReadRunningAverage() << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; - drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - - voxelStats.str(""); - long int voxelsBytesPerColored = voxels.getVoxelsColored() ? voxels.getVoxelsBytesRead()/voxels.getVoxelsColored() : 0; - long int voxelsBytesPerColoredAvg = voxels.getVoxelsColoredRunningAverage() ? - voxels.getVoxelsBytesReadRunningAverage()/voxels.getVoxelsColoredRunningAverage() : 0; - - voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored - << " (" << voxelsBytesPerColoredAvg << "/sec in last "<< COUNTETSTATS_TIME_FRAME << " seconds) "; - drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - if (::perfStatsOn) { // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups @@ -1297,7 +1269,7 @@ void *networkReceive(void *args) case PACKET_HEADER_ERASE_VOXEL: voxels.parseData(incomingPacket, bytesReceived); break; - case PACKET_HEADER_BULK_AVATAR_DATA: + case PACKET_HEADER_BULK_AVATAR_DATA: AgentList::getInstance()->processBulkAgentData(&senderAddress, incomingPacket, bytesReceived, diff --git a/libraries/shared/src/CounterStats.cpp b/libraries/shared/src/CounterStats.cpp deleted file mode 100644 index 51d991f0f1..0000000000 --- a/libraries/shared/src/CounterStats.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// CounterStats.cpp -// hifi -// -// Created by Brad Hefta-Gaub on 2013/04/08. -// -// Poor-man's counter stats collector class. Useful for collecting running averages -// and other stats for countable things. -// -// - -#include "CounterStats.h" -#include - -#ifdef _WIN32 -#include "Systime.h" -#else -#include -#endif -#include -#include -#include "shared_Log.h" - -//private: -// long int currentCount; -// long int currentDelta; -// double currentTime; -// double totalTime; -// -// long int countSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; -// long int deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; -// double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP] = {}; -// int sampleAt; - - -CounterStatHistory::CounterStatHistory() : - currentCount(0), - currentDelta(0), - currentTime(0.0), - lastCount(0), - lastTime(0.0), - totalTime(0.0), - sampleAt(-1), - sampleCount(0) { -} - -CounterStatHistory::CounterStatHistory(std::string myName) : - name(myName), - currentCount(0), - currentDelta(0), - currentTime(0.0), - lastCount(0), - lastTime(0.0), - totalTime(0.0), - sampleAt(-1), - sampleCount(0) { -} - - -CounterStatHistory::CounterStatHistory(std::string myName, double initialTime, long initialCount) : - name(myName), - currentCount(initialCount), - currentDelta(0), - currentTime(initialTime), - lastCount(initialCount), - lastTime(initialTime), - totalTime(initialTime), - sampleAt(-1), - sampleCount(0) { -} - -void CounterStatHistory::init() { - currentCount = 0; - currentDelta = 0; - currentTime = 0.0; - lastCount = 0; - lastTime = 0.0; - totalTime = 0.0; - sampleAt = -1; - sampleCount = 0; -} - -void CounterStatHistory::recordSample(long thisCount) { - timeval now; - gettimeofday(&now,NULL); - double nowSeconds = (now.tv_usec/1000000.0)+(now.tv_sec); - this->recordSample(nowSeconds,thisCount); -} - -void CounterStatHistory::recordSample(double thisTime, long thisCount) { - - // how much did we change since last sample? - long thisDelta = thisCount - this->lastCount; - double elapsed = thisTime - this->lastTime; - - // record the latest values - this->currentCount = thisCount; - this->currentTime = thisTime; - this->currentDelta = thisDelta; - - //printLog("CounterStatHistory[%s]::recordSample(thisTime %lf, thisCount= %ld)\n",this->name.c_str(),thisTime,thisCount); - - // if more than 1/10th of a second has passed, then record - // things in our rolling history - if (elapsed > 0.1) { - this->lastTime = thisTime; - this->lastCount = thisCount; - - // record it in our history... - this->sampleAt = (this->sampleAt+1)%COUNTETSTATS_SAMPLES_TO_KEEP; - if (this->sampleCountsampleCount++; - } - this->countSamples[this->sampleAt]=thisCount; - this->timeSamples[this->sampleAt]=thisTime; - this->deltaSamples[this->sampleAt]=thisDelta; - - //printLog("CounterStatHistory[%s]::recordSample() ACTUALLY RECORDING IT sampleAt=%d thisTime %lf, thisCount= %ld)\n",this->name.c_str(),this->sampleAt,thisTime,thisCount); - - } - -} - -long CounterStatHistory::getRunningAverage() { - // before we calculate our running average, always "reset" the current count, with the current time - // this will flush out old data, if we haven't been adding any new data. - this->recordSample(this->currentCount); - - long runningTotal = 0; - double minTime = this->timeSamples[0]; - double maxTime = this->timeSamples[0]; - - for (int i =0; i < this->sampleCount; i++) { - minTime = std::min(minTime,this->timeSamples[i]); - maxTime = std::max(maxTime,this->timeSamples[i]); - runningTotal += this->deltaSamples[i]; - } - - double elapsedTime = maxTime-minTime; - long runningAverage = runningTotal/elapsedTime; - return runningAverage; -} diff --git a/libraries/shared/src/CounterStats.h b/libraries/shared/src/CounterStats.h deleted file mode 100644 index 81e34853ef..0000000000 --- a/libraries/shared/src/CounterStats.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// CounterStats.h -// hifi -// -// Created by Brad Hefta-Gaub on 3/29/13. -// -// Poor-man's counter stats collector class. Useful for collecting running averages -// and other stats for countable things. -// -// - -#ifndef __hifi__CounterStats__ -#define __hifi__CounterStats__ - -#include -#include -#include - -// TIME_FRAME should be SAMPLES_TO_KEEP * TIME_BETWEEN_SAMPLES -#define COUNTETSTATS_SAMPLES_TO_KEEP 50 -#define COUNTETSTATS_TIME_BETWEEN_SAMPLES 0.1 -#define COUNTETSTATS_TIME_FRAME (COUNTETSTATS_SAMPLES_TO_KEEP*COUNTETSTATS_TIME_BETWEEN_SAMPLES) - -class CounterStatHistory { -public: - std::string name; - - CounterStatHistory(); - CounterStatHistory(std::string myName); - CounterStatHistory(std::string myName, double initialTime, long initialCount); - - void recordSample(long thisCount); - void recordSample(double thisTime, long thisCount); - long getRunningAverage(); - - long getAverage() { - return currentCount/totalTime; - }; - - double getTotalTime() { - return totalTime; - }; - long getCount() { - return currentCount; - }; -private: - void init(); - - long currentCount; - long currentDelta; - double currentTime; - - long lastCount; - double lastTime; - - double totalTime; - - long countSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; - long deltaSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; - double timeSamples[COUNTETSTATS_SAMPLES_TO_KEEP]; - int sampleAt; - int sampleCount; -}; - -#endif /* defined(__hifi__CounterStat__) */ diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp new file mode 100644 index 0000000000..94ae96f5d2 --- /dev/null +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -0,0 +1,51 @@ +// +// SimpleMovingAverage.cpp +// hifi +// +// Created by Stephen Birarda on 4/18/13. +// +// + +#include "SharedUtil.h" +#include "SimpleMovingAverage.h" + +SimpleMovingAverage::SimpleMovingAverage(float numSamplesToAverage) : + _numSamples(0), + _numSamplesToAverage(numSamplesToAverage), + _average(0), + _eventDeltaAverage(0) { +} + +int SimpleMovingAverage::updateAverage(float sample) { + if (_numSamples > 0) { + + float firstCoefficient = 1 - (1.0f / _numSamplesToAverage); + float secondCoefficient = (1.0f / _numSamplesToAverage); + + _average = (firstCoefficient * _average) + (secondCoefficient * sample); + + float eventDelta = (usecTimestampNow() - _lastEventTimestamp) / 1000000; + + if (_numSamples > 1) { + _eventDeltaAverage = (firstCoefficient * _eventDeltaAverage) + + (secondCoefficient * eventDelta); + } else { + _eventDeltaAverage = eventDelta; + } + } else { + _average = sample; + _eventDeltaAverage = 0; + } + + _lastEventTimestamp = usecTimestampNow(); + + return ++_numSamples; +} + +void SimpleMovingAverage::reset() { + _numSamples = 0; +} + +float SimpleMovingAverage::getAverageSampleValuePerSecond() { + return _average * (1 / _eventDeltaAverage); +} \ No newline at end of file diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h new file mode 100644 index 0000000000..33366ed48c --- /dev/null +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -0,0 +1,34 @@ +// +// SimpleMovingAverage.h +// hifi +// +// Created by Stephen Birarda on 4/18/13. +// Based heavily on Brad Hefta-Gaub's CounterStats class (RIP) +// +// + +#ifndef __hifi__Stats__ +#define __hifi__Stats__ + +#include + +class SimpleMovingAverage { +public: + SimpleMovingAverage(float numSamplesToAverage); + + int updateAverage(float sample); + void reset(); + + int getSampleCount() { return _numSamples; }; + float getAverage() { return _average; }; + float getEventDeltaAverage() { return _eventDeltaAverage; }; + float getAverageSampleValuePerSecond(); +private: + int _numSamples; + int _numSamplesToAverage; + double _lastEventTimestamp; + float _average; + float _eventDeltaAverage; +}; + +#endif /* defined(__hifi__Stats__) */ diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 173fe1a38b..2c2599bc80 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -15,7 +15,6 @@ #include "SharedUtil.h" #include "voxels_Log.h" #include "PacketHeaders.h" -#include "CounterStats.h" #include "OctalCode.h" #include "VoxelTree.h" #include // to load voxels from file @@ -46,19 +45,17 @@ int boundaryDistanceForRenderLevel(unsigned int renderLevel) { } } -VoxelTree::VoxelTree() { +VoxelTree::VoxelTree() : + voxelsCreated(0), + voxelsColored(0), + voxelsBytesRead(0), + voxelsCreatedStats(100), + voxelsColoredStats(100), + voxelsBytesReadStats(100) { + rootNode = new VoxelNode(); rootNode->octalCode = new unsigned char[1]; *rootNode->octalCode = 0; - - // Some stats tracking - this->voxelsCreated = 0; // when a voxel is created in the tree (object new'd) - this->voxelsColored = 0; // when a voxel is colored/set in the tree (object may have already existed) - this->voxelsBytesRead = 0; - voxelsCreatedStats.name = "voxelsCreated"; - voxelsColoredStats.name = "voxelsColored"; - voxelsBytesReadStats.name = "voxelsBytesRead"; - } VoxelTree::~VoxelTree() { @@ -126,14 +123,14 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, if (destinationNode->children[i] == NULL) { destinationNode->addChildAtIndex(i); this->voxelsCreated++; - this->voxelsCreatedStats.recordSample(this->voxelsCreated); + this->voxelsCreatedStats.updateAverage(1); } // pull the color for this child memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3); destinationNode->children[i]->color[3] = 1; this->voxelsColored++; - this->voxelsColoredStats.recordSample(this->voxelsColored); + this->voxelsColoredStats.updateAverage(1); bytesRead += 3; } @@ -156,7 +153,7 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, // add a child at that index, if it doesn't exist destinationNode->addChildAtIndex(childIndex); this->voxelsCreated++; - this->voxelsCreatedStats.recordSample(this->voxelsCreated); + this->voxelsCreatedStats.updateAverage(this->voxelsCreated); } // tell the child to read the subsequent data @@ -184,7 +181,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt readNodeData(bitstreamRootNode, bitstream + octalCodeBytes, bufferSizeBytes - octalCodeBytes); this->voxelsBytesRead += bufferSizeBytes; - this->voxelsBytesReadStats.recordSample(this->voxelsBytesRead); + this->voxelsBytesReadStats.updateAverage(bufferSizeBytes); } // Note: uses the codeColorBuffer format, but the color's are ignored, because diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 618a3710ae..4c18a23028 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -9,7 +9,7 @@ #ifndef __hifi__VoxelTree__ #define __hifi__VoxelTree__ -#include "CounterStats.h" +#include "SimpleMovingAverage.h" #include "VoxelNode.h" #include "MarkerNode.h" @@ -20,13 +20,15 @@ const int TREE_SCALE = 10; class VoxelTree { public: + // when a voxel is created in the tree (object new'd) long voxelsCreated; + // when a voxel is colored/set in the tree (object may have already existed) long voxelsColored; long voxelsBytesRead; - - CounterStatHistory voxelsCreatedStats; - CounterStatHistory voxelsColoredStats; - CounterStatHistory voxelsBytesReadStats; + + SimpleMovingAverage voxelsCreatedStats; + SimpleMovingAverage voxelsColoredStats; + SimpleMovingAverage voxelsBytesReadStats; VoxelTree(); ~VoxelTree();