diff --git a/injector/src/injector.cpp b/injector/src/injector.cpp index e33398370e..3845370178 100644 --- a/injector/src/injector.cpp +++ b/injector/src/injector.cpp @@ -147,7 +147,7 @@ int main(int argc, char* argv[]) srand(time(0)); int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1)); - UDPSocket *streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT); + streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT); if (processParameters(argc, argv)) { if (sourceAudioFile) { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 670bad9655..c03abf00f7 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -53,6 +53,7 @@ #include "Oscilloscope.h" #include "UDPSocket.h" #include "SerialInterface.h" +#include #include using namespace std; @@ -257,7 +258,18 @@ void display_stats(void) voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered(); drawtext(10,70,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); - + // Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups + char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1]; + int lines = PerfStat::DumpStats(perfStatLinesArray); + int atZ = 150; // arbitrary place on screen that looks good + for (int line=0; line < lines; line++) { + drawtext(10,atZ,0.10f, 0, 1.0, 0, perfStatLinesArray[line]); + delete perfStatLinesArray[line]; // we're responsible for cleanup + perfStatLinesArray[line]=NULL; + atZ+=20; // height of a line + } + delete []perfStatLinesArray; // we're responsible for cleanup + /* std::stringstream angles; angles << "render_yaw: " << myHead.getRenderYaw() << ", Yaw: " << myHead.getYaw(); @@ -272,7 +284,6 @@ void display_stats(void) myHead.getYaw(), myHead.getRenderYaw()); drawtext(10, 50, 0.10, 0, 1.0, 0, adc); */ - } void initDisplay(void) @@ -464,6 +475,8 @@ int render_test_direction = 1; void display(void) { + PerfStat("display"); + glEnable (GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); @@ -777,6 +790,7 @@ void *networkReceive(void *args) while (!stopNetworkReceiveThread) { if (agentList.getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { + PerfStat("networkReceive receive()"); packetcount++; bytescount += bytesReceived; diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index ce0e5c16a0..fe5b09fb26 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -30,7 +30,7 @@ #include #include #include -#endif _WIN32 +#endif //_WIN32 const unsigned short MIXER_LISTEN_PORT = 55443; diff --git a/shared/src/PerfStat.cpp b/shared/src/PerfStat.cpp new file mode 100644 index 0000000000..02ec74859a --- /dev/null +++ b/shared/src/PerfStat.cpp @@ -0,0 +1,102 @@ +// +// HiFiPerfStat.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 3/29/13. +// +// Poor-man's performance stats collector class. Useful for collecting timing +// details from various portions of the code. +// +// + +#include "PerfStat.h" +#include +#include +#include +#include + +// Static class members initialization here! +std::map > PerfStat::groupHistoryMap; +bool PerfStat::wantDebugOut = false; +timeval PerfStat::firstDumpTime; +bool PerfStat::firstDumpTimeSet = false; + +// Constructor handles starting the timer +PerfStat::PerfStat(std::string groupName) { + this->group = groupName; + gettimeofday(&this->start,NULL); + + // If this is our first ever PerfStat object, we'll also initialize this + if (!firstDumpTimeSet) { + gettimeofday(&firstDumpTime,NULL); + firstDumpTimeSet=true; + } +} + +// Destructor handles recording all of our stats +PerfStat::~PerfStat() { + timeval end; + gettimeofday(&end,NULL); + double elapsed = ((end.tv_usec-start.tv_usec)/1000000.0)+(end.tv_sec-start.tv_sec); + + double average = elapsed; + double totalTime = elapsed; + long int count = 1; + + // check to see if this group exists in the history... + if (groupHistoryMap.find(group) == groupHistoryMap.end()) { + groupHistoryMap[group]=PerfStatHistory(group,elapsed,1); + } else { + PerfStatHistory history = groupHistoryMap[group]; + history.recordTime(elapsed); + groupHistoryMap[group] = history; + average = history.getAverage(); + count = history.getCount(); + totalTime = history.getTotalTime(); + } + + if (wantDebugOut) { + printf("PerfStats: %s elapsed:%f average:%lf count:%ld total:%lf ut:%d us:%d ue:%d t:%ld s:%ld e:%ld\n", + this->group.c_str(),elapsed,average,count,totalTime, + (end.tv_usec-start.tv_usec),start.tv_usec,end.tv_usec, + (end.tv_sec-start.tv_sec),start.tv_sec,end.tv_sec + ); + } +}; + +// How many groups have we added? +int PerfStat::getGroupCount() { + return groupHistoryMap.size(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Method: DumpStats() +// Description: Generates some lines of debug stats for all the groups of PerfStats you've created. +// Note: Caller is responsible for allocating an array of char*'s that is large enough to hold +// groupCount + 1. Caller is also responsible for deleting all this memory. +int PerfStat::DumpStats(char** array) { + // If we haven't yet set a dump time, we'll also initialize this now, but this is unlikely + if (!firstDumpTimeSet) { + gettimeofday(&firstDumpTime,NULL); + firstDumpTimeSet=true; + } + + timeval now; + gettimeofday(&now,NULL); + double elapsed = ((now.tv_usec-firstDumpTime.tv_usec)/1000000.0)+(now.tv_sec-firstDumpTime.tv_sec); + + array[0] = new char[MAX_PERFSTAT_DEBUG_LINE_LEN]; + snprintf(array[0],MAX_PERFSTAT_DEBUG_LINE_LEN,"PerfStats:"); + int lineCount=1; + // For each active performance group + for (PerfStatMapItr i = groupHistoryMap.begin(); i != groupHistoryMap.end(); i++) { + float percent = (i->second.getTotalTime()/elapsed) * 100.0; + + array[lineCount] = new char[MAX_PERFSTAT_DEBUG_LINE_LEN]; + snprintf(array[lineCount],MAX_PERFSTAT_DEBUG_LINE_LEN,"%s Avg: %lf Num: %ld TTime: %lf (%.2f%%)", + i->second.group.c_str(),i->second.getAverage(),i->second.getCount(),i->second.getTotalTime(),percent); + lineCount++; + } + return lineCount; +} + diff --git a/shared/src/PerfStat.h b/shared/src/PerfStat.h new file mode 100644 index 0000000000..3bb75e7892 --- /dev/null +++ b/shared/src/PerfStat.h @@ -0,0 +1,76 @@ +// +// HiFiPerfStat.h +// hifi +// +// Created by Brad Hefta-Gaub on 3/29/13. +// +// Poor-man's performance stats collector class. Useful for collecting timing +// details from various portions of the code. +// +// + +#ifndef __hifi__PerfStat__ +#define __hifi__PerfStat__ + +#include +#include +#include + +class PerfStatHistory { + +private: + long int count; + double totalTime; +public: + std::string group; + + PerfStatHistory(): count(0), totalTime(0.0) {}; + PerfStatHistory(std::string myGroup, double initialTime, long int initialCount) : + count(initialCount), totalTime(initialTime), group(myGroup) {}; + + void recordTime(double thisTime) { + totalTime+=thisTime; + count++; + }; + double getAverage() { + return totalTime/count; + }; + double getTotalTime() { + return totalTime; + }; + long int getCount() { + return count; + }; + + // needed for map template? Maybe not. + bool operator<( const PerfStatHistory& other) const { + return group < other.group; + } +}; + +#define MAX_PERFSTAT_DEBUG_LINE_LEN 200 + +class PerfStat { +private: + static std::map > groupHistoryMap; + + static timeval firstDumpTime; + static bool firstDumpTimeSet; + + std::string group; + timeval start; + +public: + PerfStat(std::string groupName); + ~PerfStat(); + + // Format debug stats into buffer, returns number of "lines" of stats + static int DumpStats(char** array); + static int getGroupCount(); + static bool wantDebugOut; +}; + +typedef std::map >::iterator PerfStatMapItr; + + +#endif /* defined(__hifi__PerfStat__) */