From b9a1faf2848697ade81f426b939f8718b7a95003 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 14:46:39 -0700 Subject: [PATCH 1/7] 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(); From 588fc67cb944c69803cfaaabc328cd0dad88e274 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 15:02:26 -0700 Subject: [PATCH 2/7] add SimpleMovingAverage to each Agent, collect bytes received stats --- interface/src/main.cpp | 2 +- libraries/shared/src/Agent.cpp | 35 ++++++++++++++++++++++ libraries/shared/src/Agent.h | 19 ++++++++++-- libraries/shared/src/AgentList.cpp | 2 ++ libraries/shared/src/SimpleMovingAverage.h | 2 +- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 4e43381edc..09486a9c90 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1269,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/Agent.cpp b/libraries/shared/src/Agent.cpp index e50392c96f..93925a04a5 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -37,6 +37,7 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent activeSocket = NULL; linkedData = NULL; + _movingAverage = NULL; deleteMutex = new pthread_mutex_t; pthread_mutex_init(deleteMutex, NULL); @@ -69,6 +70,13 @@ Agent::Agent(const Agent &otherAgent) { linkedData = NULL; } + if (otherAgent._movingAverage != NULL) { + _movingAverage = new SimpleMovingAverage(100); + memcpy(_movingAverage, otherAgent._movingAverage, sizeof(SimpleMovingAverage)); + } else { + _movingAverage = NULL; + } + deleteMutex = new pthread_mutex_t; pthread_mutex_init(deleteMutex, NULL); } @@ -89,6 +97,7 @@ void Agent::swap(Agent &first, Agent &second) { swap(first.agentId, second.agentId); swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs); swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs); + swap(first._movingAverage, second._movingAverage); swap(first.deleteMutex, second.deleteMutex); } @@ -99,6 +108,7 @@ Agent::~Agent() { delete publicSocket; delete localSocket; delete linkedData; + delete _movingAverage; } char Agent::getType() const { @@ -211,6 +221,31 @@ bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, cha && socketMatch(localSocket, otherLocalSocket); } +void Agent::recordBytesReceived(int bytesReceived) { + if (_movingAverage == NULL) { + printf("Setting up the moving average for agent\n"); + _movingAverage = new SimpleMovingAverage(100); + } + + _movingAverage->updateAverage((float) bytesReceived); +} + +float Agent::getAveragePacketsPerSecond() { + if (_movingAverage != NULL) { + return (1 / _movingAverage->getEventDeltaAverage()); + } else { + return 0; + } +} + +float Agent::getAverageKilobitsPerSecond() { + if (_movingAverage != NULL) { + return (_movingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000)); + } else { + return 0; + } +} + void Agent::printLog(Agent const& agent) { sockaddr_in *agentPublicSocket = (sockaddr_in *) agent.publicSocket; diff --git a/libraries/shared/src/Agent.h b/libraries/shared/src/Agent.h index 601df8d1f0..99773633b5 100644 --- a/libraries/shared/src/Agent.h +++ b/libraries/shared/src/Agent.h @@ -11,7 +11,6 @@ #include #include -#include "AgentData.h" #ifdef _WIN32 #include "Syssocket.h" @@ -19,6 +18,9 @@ #include #endif +#include "SimpleMovingAverage.h" +#include "AgentData.h" + class Agent { public: Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId); @@ -34,32 +36,45 @@ public: char getType() const; const char* getTypeName() const; void setType(char newType); + uint16_t getAgentId(); void setAgentId(uint16_t thisAgentId); + double getFirstRecvTimeUsecs(); void setFirstRecvTimeUsecs(double newTimeUsecs); + double getLastRecvTimeUsecs(); void setLastRecvTimeUsecs(double newTimeUsecs); + sockaddr* getPublicSocket(); void setPublicSocket(sockaddr *newSocket); sockaddr* getLocalSocket(); void setLocalSocket(sockaddr *newSocket); sockaddr* getActiveSocket(); + void activatePublicSocket(); void activateLocalSocket(); + AgentData* getLinkedData(); void setLinkedData(AgentData *newData); + + void recordBytesReceived(int bytesReceived); + float getAverageKilobitsPerSecond(); + float getAveragePacketsPerSecond(); static void printLog(Agent const&); friend std::ostream& operator<<(std::ostream& os, const Agent* agent); private: void swap(Agent &first, Agent &second); + sockaddr *publicSocket, *localSocket, *activeSocket; char type; uint16_t agentId; double firstRecvTimeUsecs; double lastRecvTimeUsecs; - AgentData *linkedData; + SimpleMovingAverage* _movingAverage; + AgentData* linkedData; + }; std::ostream& operator<<(std::ostream& os, const Agent* agent); diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 36627d409e..9749e390c0 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -108,6 +108,7 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac if (bulkSendAgentIndex >= 0) { Agent *bulkSendAgent = &agents[bulkSendAgentIndex]; bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow()); + bulkSendAgent->recordBytesReceived(numTotalBytes); } unsigned char *startPosition = packetData; @@ -144,6 +145,7 @@ void AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *pack void AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) { agent->setLastRecvTimeUsecs(usecTimestampNow()); + agent->recordBytesReceived(dataBytes); if (agent->getLinkedData() == NULL) { if (linkedDataCreateCallback != NULL) { diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index 33366ed48c..e653e89d85 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -3,7 +3,7 @@ // hifi // // Created by Stephen Birarda on 4/18/13. -// Based heavily on Brad Hefta-Gaub's CounterStats class (RIP) +// Replaces Brad Hefta-Gaub's CounterStats class (RIP) // // From 44cb57afad7000428facd629ad886d410eca9355 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 15:33:17 -0700 Subject: [PATCH 3/7] put back brad's voxel stats, he loves them too much --- interface/src/VoxelSystem.cpp | 6 +++--- interface/src/VoxelSystem.h | 2 +- interface/src/main.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index cf88a199d0..7b22525fde 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -102,15 +102,15 @@ long int VoxelSystem::getVoxelsColored() { } float VoxelSystem::getVoxelsColoredPerSecondAverage() { - return tree->voxelsColoredStats.getEventDeltaAverage(); + return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); } long int VoxelSystem::getVoxelsBytesRead() { return tree->voxelsBytesRead; } -float VoxelSystem::getVoxelsBytesReadAverage() { - return tree->voxelsBytesReadStats.getAverage(); +float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { + return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 3ca39d75bf..76aaf57a4e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -42,7 +42,7 @@ public: long int getVoxelsBytesRead(); float getVoxelsCreatedPerSecondAverage(); float getVoxelsColoredPerSecondAverage(); - float getVoxelsBytesReadAverage(); + float getVoxelsBytesReadPerSecondAverage(); private: int voxelsRendered; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 09486a9c90..5adea8abff 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -236,6 +236,33 @@ 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.getVoxelsCreatedPerSecondAverage() + << "/sec) "; + drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredPerSecondAverage() + << "/sec) "; + drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead() + << " (" << voxels.getVoxelsBytesReadPerSecondAverage() << " Bps)"; + drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + float voxelsBytesPerColored = voxels.getVoxelsColored() + ? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored()) + : 0; + + voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored; + 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 From cf1254f53b5e1bb3980f71c275b1f7e320d166a9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 15:45:20 -0700 Subject: [PATCH 4/7] rename the _movingAverage variable so it is more descriptive --- libraries/shared/src/Agent.cpp | 29 ++++++++++++++--------------- libraries/shared/src/Agent.h | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index 93925a04a5..b329b7faaa 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -37,7 +37,7 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent activeSocket = NULL; linkedData = NULL; - _movingAverage = NULL; + _bytesReceivedMovingAverage = NULL; deleteMutex = new pthread_mutex_t; pthread_mutex_init(deleteMutex, NULL); @@ -70,11 +70,11 @@ Agent::Agent(const Agent &otherAgent) { linkedData = NULL; } - if (otherAgent._movingAverage != NULL) { - _movingAverage = new SimpleMovingAverage(100); - memcpy(_movingAverage, otherAgent._movingAverage, sizeof(SimpleMovingAverage)); + if (otherAgent._bytesReceivedMovingAverage != NULL) { + _bytesReceivedMovingAverage = new SimpleMovingAverage(100); + memcpy(_bytesReceivedMovingAverage, otherAgent._bytesReceivedMovingAverage, sizeof(SimpleMovingAverage)); } else { - _movingAverage = NULL; + _bytesReceivedMovingAverage = NULL; } deleteMutex = new pthread_mutex_t; @@ -97,7 +97,7 @@ void Agent::swap(Agent &first, Agent &second) { swap(first.agentId, second.agentId); swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs); swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs); - swap(first._movingAverage, second._movingAverage); + swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage); swap(first.deleteMutex, second.deleteMutex); } @@ -108,7 +108,7 @@ Agent::~Agent() { delete publicSocket; delete localSocket; delete linkedData; - delete _movingAverage; + delete _bytesReceivedMovingAverage; } char Agent::getType() const { @@ -209,7 +209,6 @@ void Agent::setLinkedData(AgentData *newData) { linkedData = newData; } - bool Agent::operator==(const Agent& otherAgent) { return matches(otherAgent.publicSocket, otherAgent.localSocket, otherAgent.type); } @@ -222,25 +221,25 @@ bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, cha } void Agent::recordBytesReceived(int bytesReceived) { - if (_movingAverage == NULL) { + if (_bytesReceivedMovingAverage == NULL) { printf("Setting up the moving average for agent\n"); - _movingAverage = new SimpleMovingAverage(100); + _bytesReceivedMovingAverage = new SimpleMovingAverage(100); } - _movingAverage->updateAverage((float) bytesReceived); + _bytesReceivedMovingAverage->updateAverage((float) bytesReceived); } float Agent::getAveragePacketsPerSecond() { - if (_movingAverage != NULL) { - return (1 / _movingAverage->getEventDeltaAverage()); + if (_bytesReceivedMovingAverage != NULL) { + return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage()); } else { return 0; } } float Agent::getAverageKilobitsPerSecond() { - if (_movingAverage != NULL) { - return (_movingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000)); + if (_bytesReceivedMovingAverage != NULL) { + return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000)); } else { return 0; } diff --git a/libraries/shared/src/Agent.h b/libraries/shared/src/Agent.h index 99773633b5..14942defcb 100644 --- a/libraries/shared/src/Agent.h +++ b/libraries/shared/src/Agent.h @@ -72,7 +72,7 @@ private: uint16_t agentId; double firstRecvTimeUsecs; double lastRecvTimeUsecs; - SimpleMovingAverage* _movingAverage; + SimpleMovingAverage* _bytesReceivedMovingAverage; AgentData* linkedData; }; From 6e540d166b5b4040f27dd08e635b241bd0a7b0f8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 16:30:38 -0700 Subject: [PATCH 5/7] add a decay to the event delta average --- libraries/shared/src/SimpleMovingAverage.cpp | 25 +++++++++++--------- libraries/shared/src/SimpleMovingAverage.h | 8 ++++--- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index 94ae96f5d2..db433c020f 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -9,26 +9,24 @@ #include "SharedUtil.h" #include "SimpleMovingAverage.h" -SimpleMovingAverage::SimpleMovingAverage(float numSamplesToAverage) : +SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) : _numSamples(0), - _numSamplesToAverage(numSamplesToAverage), _average(0), - _eventDeltaAverage(0) { + _eventDeltaAverage(0), + WEIGHTING(1.0f / numSamplesToAverage), + ONE_MINUS_WEIGHTING(1 - WEIGHTING) { + } int SimpleMovingAverage::updateAverage(float sample) { if (_numSamples > 0) { - - float firstCoefficient = 1 - (1.0f / _numSamplesToAverage); - float secondCoefficient = (1.0f / _numSamplesToAverage); - - _average = (firstCoefficient * _average) + (secondCoefficient * sample); + _average = (ONE_MINUS_WEIGHTING * _average) + (WEIGHTING * sample); float eventDelta = (usecTimestampNow() - _lastEventTimestamp) / 1000000; if (_numSamples > 1) { - _eventDeltaAverage = (firstCoefficient * _eventDeltaAverage) + - (secondCoefficient * eventDelta); + _eventDeltaAverage = (ONE_MINUS_WEIGHTING * _eventDeltaAverage) + + (WEIGHTING * eventDelta); } else { _eventDeltaAverage = eventDelta; } @@ -46,6 +44,11 @@ void SimpleMovingAverage::reset() { _numSamples = 0; } +float SimpleMovingAverage::getEventDeltaAverage() { + return (ONE_MINUS_WEIGHTING * _eventDeltaAverage) + + (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000)); +} + float SimpleMovingAverage::getAverageSampleValuePerSecond() { - return _average * (1 / _eventDeltaAverage); + return _average * (1 / getEventDeltaAverage()); } \ No newline at end of file diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index e653e89d85..e24b639133 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -14,21 +14,23 @@ class SimpleMovingAverage { public: - SimpleMovingAverage(float numSamplesToAverage); + SimpleMovingAverage(int numSamplesToAverage); int updateAverage(float sample); void reset(); int getSampleCount() { return _numSamples; }; float getAverage() { return _average; }; - float getEventDeltaAverage() { return _eventDeltaAverage; }; + float getEventDeltaAverage(); float getAverageSampleValuePerSecond(); private: int _numSamples; - int _numSamplesToAverage; double _lastEventTimestamp; float _average; float _eventDeltaAverage; + + const float WEIGHTING; + const float ONE_MINUS_WEIGHTING; }; #endif /* defined(__hifi__Stats__) */ From d937ef17f60d561a79aac9552ba2f05afe6fc976 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 16:38:46 -0700 Subject: [PATCH 6/7] remove extra debug line --- libraries/shared/src/Agent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index b329b7faaa..d05afe5e26 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -222,7 +222,6 @@ bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, cha void Agent::recordBytesReceived(int bytesReceived) { if (_bytesReceivedMovingAverage == NULL) { - printf("Setting up the moving average for agent\n"); _bytesReceivedMovingAverage = new SimpleMovingAverage(100); } From daac10511e1a70506d23dc46ff265dba2fda5de2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Apr 2013 16:58:08 -0700 Subject: [PATCH 7/7] output avatar mixer stats below the voxel stats --- domain-server/src/main.cpp | 2 +- interface/src/main.cpp | 7 +++++++ libraries/shared/src/AgentList.cpp | 19 ++++++++++++++++++- libraries/shared/src/AgentList.h | 4 +++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 8ab62eaeeb..05e1583fca 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -133,7 +133,7 @@ int main(int argc, const char * argv[]) if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) { - if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->getType()) == NULL) { + if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) { // this is an agent of which there can be multiple, just add them to the packet currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); } else { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9c548a5c33..17b8ad8ec3 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -263,6 +263,13 @@ void displayStats(void) voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored; drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER); + char avatarMixerStats[200]; + sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps", + roundf(avatarMixer->getAverageKilobitsPerSecond()), + roundf(avatarMixer->getAveragePacketsPerSecond())); + drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats); if (::perfStatsOn) { // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 9749e390c0..5316eee79c 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -24,7 +24,12 @@ using shared_lib::printLog; -const char * SOLO_AGENT_TYPES_STRING = "MV"; +const char SOLO_AGENT_TYPES_STRING[] = { + AGENT_TYPE_AVATAR_MIXER, + AGENT_TYPE_AUDIO_MIXER, + AGENT_TYPE_VOXEL +}; + char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; @@ -287,6 +292,18 @@ void AgentList::handlePingReply(sockaddr *agentAddress) { } } +Agent* AgentList::soloAgentOfType(char agentType) { + if (memchr(SOLO_AGENT_TYPES_STRING, agentType, 1)) { + for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + if (agent->getType() == agentType) { + return &*agent; + } + } + } + + return NULL; +} + void *pingUnknownAgents(void *args) { AgentList *agentList = (AgentList *)args; diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index 4dfa9359bf..adc66333f9 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -22,7 +22,7 @@ const int MAX_PACKET_SIZE = 1500; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; -extern const char *SOLO_AGENT_TYPES_STRING; +extern const char SOLO_AGENT_TYPES_STRING[]; extern char DOMAIN_HOSTNAME[]; extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup @@ -59,6 +59,8 @@ public: char getOwnerType(); unsigned int getSocketListenPort(); + Agent* soloAgentOfType(char agentType); + void startSilentAgentRemovalThread(); void stopSilentAgentRemovalThread(); void startDomainServerCheckInThread();