From af8438b098b8eeb7e11241406f4751735c1f9d80 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 11 Nov 2013 16:31:36 -0800 Subject: [PATCH 1/4] add stats to voxel server to show average voxel edit packet statistics --- .../voxel-server-library/src/VoxelServer.cpp | 110 +++++++++++++----- .../src/VoxelServerPacketProcessor.cpp | 59 +++++++++- .../src/VoxelServerPacketProcessor.h | 22 ++++ libraries/voxels/src/JurisdictionMap.cpp | 2 +- libraries/voxels/src/JurisdictionMap.h | 2 +- .../voxels/src/VoxelEditPacketSender.cpp | 2 +- 6 files changed, 159 insertions(+), 38 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 1ce0bcd59d..320e2c7de0 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -128,15 +128,26 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { return 1; } #endif - + + bool showStats = false; if (strcmp(ri->uri, "/") == 0 && strcmp(ri->request_method, "GET") == 0) { + showStats = true; + } + + if (strcmp(ri->uri, "/resetStats") == 0 && strcmp(ri->request_method, "GET") == 0) { + GetInstance()->_voxelServerPacketProcessor->resetStats(); + showStats = true; + } + + if (showStats) { uint64_t checkSum; // return a 200 - mg_printf(connection, "%s", "HTTP/1.0 200 OK\r\n\r\n"); - mg_printf(connection, "%s", "Your Voxel Server is running.\r\n"); + mg_printf(connection, "%s", "HTTP/1.0 200 OK\r\n"); + mg_printf(connection, "%s", "Content-Type: text/html\r\n\r\n"); + mg_printf(connection, "%s", "\r\n"); + mg_printf(connection, "%s", "
\r\n");
+        mg_printf(connection, "%s", "Your Voxel Server is running... [RELOAD]\r\n");
 
-
-        mg_printf(connection, "%s", "\r\n");
         tm* localtm = localtime(&GetInstance()->_started);
         const int MAX_TIME_LENGTH = 128;
         char buffer[MAX_TIME_LENGTH];
@@ -206,7 +217,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
             if (minutes > 0) {
                 mg_printf(connection, "%d minute%s ", minutes, (minutes > 1) ? "s" : "");
             }
-            if (seconds > 0) {
+            if (seconds >= 0) {
                 mg_printf(connection, "%.3f seconds", seconds);
             }
             mg_printf(connection, "%s", "\r\n");
@@ -218,15 +229,70 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
         mg_printf(connection, "%s", "\r\n");
 
         mg_printf(connection, "%s", "\r\n");
-        mg_printf(connection, "%s", "Configuration: \r\n     ");
+
+        mg_printf(connection, "%s", "Configuration:\r\n");
+
         for (int i = 1; i < GetInstance()->_argc; i++) {
             mg_printf(connection, "%s ", GetInstance()->_argv[i]);
         }
+        mg_printf(connection, "%s", "\r\n"); // one to end the config line
+        mg_printf(connection, "%s", "\r\n"); // two more for spacing
+        mg_printf(connection, "%s", "\r\n");
+
+        // display scene stats
+        unsigned long nodeCount = VoxelNode::getNodeCount();
+        unsigned long internalNodeCount = VoxelNode::getInternalNodeCount();
+        unsigned long leafNodeCount = VoxelNode::getLeafNodeCount();
+        
+        QLocale locale(QLocale::English);
+        const float AS_PERCENT = 100.0;
+        mg_printf(connection, "%s", "Current Nodes in scene:\r\n");
+        mg_printf(connection, "       Total Nodes: %s nodes\r\n",
+                    locale.toString((uint)nodeCount).rightJustified(16, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "    Internal Nodes: %s nodes (%5.2f%%)\r\n",
+            locale.toString((uint)internalNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
+            ((float)internalNodeCount/(float)nodeCount) * AS_PERCENT);
+        mg_printf(connection, "        Leaf Nodes: %s nodes (%5.2f%%)\r\n", 
+            locale.toString((uint)leafNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
+            ((float)leafNodeCount/(float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "%s", "\r\n");
         mg_printf(connection, "%s", "\r\n");
 
+        // display inbound packet stats
+        mg_printf(connection, "%s", "Voxel Edit Statistics... [RESET]\r\n");
+        uint64_t averageTransitTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverateTransitTimePerPacket();
+        uint64_t averageProcessTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverageProcessTimePerPacket();
+        uint64_t averageLockWaitTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverageLockWaitTimePerPacket();
+        uint64_t averageProcessTimePerVoxel = GetInstance()->_voxelServerPacketProcessor->getAverageProcessTimePerVoxel();
+        uint64_t averageLockWaitTimePerVoxel = GetInstance()->_voxelServerPacketProcessor->getAverageLockWaitTimePerVoxel();
+        uint64_t totalVoxelsProcessed = GetInstance()->_voxelServerPacketProcessor->getTotalVoxelsProcessed();
+        uint64_t totalPacketsProcessed = GetInstance()->_voxelServerPacketProcessor->getTotalPacketsProcessed();
 
-        mg_printf(connection, "%s", "Current Statistics\r\n");
+        float averageVoxelsPerPacket = totalPacketsProcessed == 0 ? 0 : totalVoxelsProcessed / totalPacketsProcessed;
+
+        const int COLUMN_WIDTH = 10;
+        mg_printf(connection, "           Total Inbound Packets: %s packets\r\n",
+            locale.toString((uint)totalPacketsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "            Total Inbound Voxels: %s voxels\r\n",
+            locale.toString((uint)totalVoxelsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "   Average Inbound Voxels/Packet: %f voxels/packet\r\n", averageVoxelsPerPacket);
+        mg_printf(connection, "     Average Transit Time/Packet: %s usecs\r\n", 
+            locale.toString((uint)averageTransitTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "     Average Process Time/Packet: %s usecs\r\n",
+            locale.toString((uint)averageProcessTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "   Average Wait Lock Time/Packet: %s usecs\r\n", 
+            locale.toString((uint)averageLockWaitTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "      Average Process Time/Voxel: %s usecs\r\n",
+            locale.toString((uint)averageProcessTimePerVoxel).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+        mg_printf(connection, "    Average Wait Lock Time/Voxel: %s usecs\r\n", 
+            locale.toString((uint)averageLockWaitTimePerVoxel).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData());
+
+        mg_printf(connection, "%s", "\r\n");
+        mg_printf(connection, "%s", "\r\n");
+
+        // display memory usage stats
+        mg_printf(connection, "%s", "Current Memory Usage Statistics\r\n");
+        mg_printf(connection, "\r\nVoxelNode size... %ld bytes\r\n", sizeof(VoxelNode));
         mg_printf(connection, "%s", "\r\n");
 
         const char* memoryScaleLabel;
@@ -251,28 +317,6 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
         mg_printf(connection, "                         Total:  %8.2f %s\r\n", 
             VoxelNode::getTotalMemoryUsage() / memoryScale, memoryScaleLabel);
 
-        mg_printf(connection, "\r\nVoxelNode size... %ld bytes\r\n", sizeof(VoxelNode));
-
-        unsigned long nodeCount = VoxelNode::getNodeCount();
-        unsigned long internalNodeCount = VoxelNode::getInternalNodeCount();
-        unsigned long leafNodeCount = VoxelNode::getLeafNodeCount();
-        
-        
-        QLocale locale(QLocale::English);
-
-        const float AS_PERCENT = 100.0;
-
-        mg_printf(connection, "%s", "\r\n");
-        mg_printf(connection, "%s", "Current Nodes in scene\r\n");
-        mg_printf(connection, "       Total Nodes: %s nodes\r\n",
-                    locale.toString((uint)nodeCount).rightJustified(16, ' ').toLocal8Bit().constData());
-        mg_printf(connection, "    Internal Nodes: %s nodes (%5.2f%%)\r\n",
-            locale.toString((uint)internalNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
-            ((float)internalNodeCount/(float)nodeCount) * AS_PERCENT);
-        mg_printf(connection, "        Leaf Nodes: %s nodes (%5.2f%%)\r\n", 
-            locale.toString((uint)leafNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
-            ((float)leafNodeCount/(float)nodeCount) * AS_PERCENT);
-
         mg_printf(connection, "%s", "\r\n");
         mg_printf(connection, "%s", "VoxelNode Children Population Statistics...\r\n");
         checkSum = 0;
@@ -325,6 +369,12 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
             VoxelNode::getCouldNotStoreFourChildrenInternally());
 #endif
 
+        mg_printf(connection, "%s", "\r\n");
+        mg_printf(connection, "%s", "\r\n");
+        mg_printf(connection, "%s", "
\r\n"); + + mg_printf(connection, "%s", "
"); + return 1; } else { // have mongoose process this request from the document_root diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index eb96706f12..9d3ffcdc51 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -15,10 +15,25 @@ #include "VoxelServerConsts.h" #include "VoxelServerPacketProcessor.h" +static QUuid DEFAULT_NODE_ID_REF; VoxelServerPacketProcessor::VoxelServerPacketProcessor(VoxelServer* myServer) : _myServer(myServer), - _receivedPacketCount(0) { + _receivedPacketCount(0), + _totalTransitTime(0), + _totalProcessTime(0), + _totalLockWaitTime(0), + _totalVoxelsInPacket(0), + _totalPackets(0) +{ +} + +void VoxelServerPacketProcessor::resetStats() { + _totalTransitTime = 0; + _totalProcessTime = 0; + _totalLockWaitTime = 0; + _totalVoxelsInPacket = 0; + _totalPackets = 0; } @@ -37,13 +52,16 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned PerformanceWarning warn(_myServer->wantShowAnimationDebug(), destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", _myServer->wantShowAnimationDebug()); - + _receivedPacketCount++; unsigned short int sequence = (*((unsigned short int*)(packetData + numBytesPacketHeader))); uint64_t sentAt = (*((uint64_t*)(packetData + numBytesPacketHeader + sizeof(sequence)))); uint64_t arrivedAt = usecTimestampNow(); uint64_t transitTime = arrivedAt - sentAt; + int voxelsInPacket = 0; + uint64_t processTime = 0; + uint64_t lockWaitTime = 0; if (_myServer->wantShowAnimationDebug() || _myServer->wantsDebugVoxelReceiving()) { printf("PROCESSING THREAD: got %s - %d command from client receivedBytes=%ld sequence=%d transitTime=%llu usecs\n", @@ -84,9 +102,20 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned delete[] vertices; } + uint64_t startLock = usecTimestampNow(); _myServer->getServerTree().lockForWrite(); + uint64_t startProcess = usecTimestampNow(); _myServer->getServerTree().readCodeColorBufferToTree(voxelData, destructive); _myServer->getServerTree().unlock(); + uint64_t endProcess = usecTimestampNow(); + + voxelsInPacket++; + + uint64_t thisProcessTime = endProcess - startProcess; + uint64_t thisLockWaitTime = startProcess - startLock; + + processTime += thisProcessTime; + lockWaitTime += thisLockWaitTime; // skip to next voxel edit record in the packet voxelData += voxelDataSize; @@ -104,10 +133,20 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned } // Make sure our Node and NodeList knows we've heard from this node. - Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress); - if (node) { - node->setLastHeardMicrostamp(usecTimestampNow()); + Node* senderNode = NodeList::getInstance()->nodeWithAddress(&senderAddress); + QUuid& nodeUUID = DEFAULT_NODE_ID_REF; + if (senderNode) { + senderNode->setLastHeardMicrostamp(usecTimestampNow()); + nodeUUID = senderNode->getUUID(); + if (debugProcessPacket) { + qDebug() << "sender has uuid=" << nodeUUID << "\n"; + } + } else { + if (debugProcessPacket) { + qDebug() << "sender has no known nodeUUID.\n"; + } } + trackInboudPackets(nodeUUID, sequence, transitTime, voxelsInPacket, processTime, lockWaitTime); } else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) { @@ -167,3 +206,13 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned } } +void VoxelServerPacketProcessor::trackInboudPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, + int voxelsInPacket, uint64_t processTime, uint64_t lockWaitTime) { + + _totalTransitTime += transitTime; + _totalProcessTime += processTime; + _totalLockWaitTime += lockWaitTime; + _totalVoxelsInPacket += voxelsInPacket; + _totalPackets++; +} + diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h index 8ef316bd23..b461c5a664 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h @@ -21,11 +21,33 @@ class VoxelServerPacketProcessor : public ReceivedPacketProcessor { public: VoxelServerPacketProcessor(VoxelServer* myServer); + uint64_t getAverateTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; } + uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; } + uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; } + uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; } + uint64_t getTotalPacketsProcessed() const { return _totalPackets; } + uint64_t getAverageProcessTimePerVoxel() const + { return _totalVoxelsInPacket == 0 ? 0 : _totalProcessTime / _totalVoxelsInPacket; } + uint64_t getAverageLockWaitTimePerVoxel() const + { return _totalVoxelsInPacket == 0 ? 0 : _totalLockWaitTime / _totalVoxelsInPacket; } + + void resetStats(); + protected: virtual void processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength); private: + void trackInboudPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, + int voxelsInPacket, uint64_t processTime, uint64_t lockWaitTime); + VoxelServer* _myServer; int _receivedPacketCount; + + uint64_t _totalTransitTime; + uint64_t _totalProcessTime; + uint64_t _totalLockWaitTime; + uint64_t _totalVoxelsInPacket; + uint64_t _totalPackets; + }; #endif // __voxel_server__VoxelServerPacketProcessor__ diff --git a/libraries/voxels/src/JurisdictionMap.cpp b/libraries/voxels/src/JurisdictionMap.cpp index c95a71ac75..00e469b03f 100644 --- a/libraries/voxels/src/JurisdictionMap.cpp +++ b/libraries/voxels/src/JurisdictionMap.cpp @@ -229,7 +229,7 @@ bool JurisdictionMap::readFromFile(const char* filename) { return true; } -void JurisdictionMap::displayDebugDetails() { +void JurisdictionMap::displayDebugDetails() const { QString rootNodeValue = octalCodeToHexString(_rootOctalCode); qDebug() << "root:" << rootNodeValue << "\n"; diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h index aafc029253..d412373faf 100644 --- a/libraries/voxels/src/JurisdictionMap.h +++ b/libraries/voxels/src/JurisdictionMap.h @@ -60,7 +60,7 @@ public: /// Available to pack an empty or unknown jurisdiction into a network packet, used when no JurisdictionMap is available static int packEmptyJurisdictionIntoMessage(unsigned char* destinationBuffer, int availableBytes); - void displayDebugDetails(); + void displayDebugDetails() const; private: void copyContents(const JurisdictionMap& other); // use assignment instead diff --git a/libraries/voxels/src/VoxelEditPacketSender.cpp b/libraries/voxels/src/VoxelEditPacketSender.cpp index 1652e22dc5..8ac2b37833 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.cpp +++ b/libraries/voxels/src/VoxelEditPacketSender.cpp @@ -191,7 +191,7 @@ void VoxelEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t le assert(voxelServersExist()); // we must have jurisdictions to be here!! - int headerBytes = numBytesForPacketHeader(buffer) + sizeof(short); + int headerBytes = numBytesForPacketHeader(buffer) + sizeof(short) + sizeof(uint64_t); unsigned char* octCode = buffer + headerBytes; // skip the packet header to get to the octcode // We want to filter out edit messages for voxel servers based on the server's Jurisdiction From 0eace966e961d0a8a589c162c4ecb02c4117f1fd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 11 Nov 2013 17:20:31 -0800 Subject: [PATCH 2/4] added support to also show inbound packet stats per sender --- .../voxel-server-library/src/VoxelServer.cpp | 40 +++++++++++++++++++ .../src/VoxelServerPacketProcessor.cpp | 33 +++++++++++++++ .../src/VoxelServerPacketProcessor.h | 30 ++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 320e2c7de0..11d7d3ff1c 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -287,6 +287,46 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { mg_printf(connection, " Average Wait Lock Time/Voxel: %s usecs\r\n", locale.toString((uint)averageLockWaitTimePerVoxel).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + + int senderNumber = 0; + NodeToSenderStatsMap& allSenderStats = GetInstance()->_voxelServerPacketProcessor->getSingleSenderStats(); + for (NodeToSenderStatsMapIterator i = allSenderStats.begin(); i != allSenderStats.end(); i++) { + senderNumber++; + // iterator->first = key + // iterator->second = value + QUuid senderID = i->first; + SingleSenderStats& senderStats = i->second; + + mg_printf(connection, "\r\n Stats for sender %d uuid: %s\r\n", senderNumber, + senderID.toString().toLocal8Bit().constData()); + + averageTransitTimePerPacket = senderStats.getAverateTransitTimePerPacket(); + averageProcessTimePerPacket = senderStats.getAverageProcessTimePerPacket(); + averageLockWaitTimePerPacket = senderStats.getAverageLockWaitTimePerPacket(); + averageProcessTimePerVoxel = senderStats.getAverageProcessTimePerVoxel(); + averageLockWaitTimePerVoxel = senderStats.getAverageLockWaitTimePerVoxel(); + totalVoxelsProcessed = senderStats.getTotalVoxelsProcessed(); + totalPacketsProcessed = senderStats.getTotalPacketsProcessed(); + + mg_printf(connection, " Total Inbound Packets: %s packets\r\n", + locale.toString((uint)totalPacketsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Total Inbound Voxels: %s voxels\r\n", + locale.toString((uint)totalVoxelsProcessed).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Average Inbound Voxels/Packet: %f voxels/packet\r\n", averageVoxelsPerPacket); + mg_printf(connection, " Average Transit Time/Packet: %s usecs\r\n", + locale.toString((uint)averageTransitTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Average Process Time/Packet: %s usecs\r\n", + locale.toString((uint)averageProcessTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Average Wait Lock Time/Packet: %s usecs\r\n", + locale.toString((uint)averageLockWaitTimePerPacket).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Average Process Time/Voxel: %s usecs\r\n", + locale.toString((uint)averageProcessTimePerVoxel).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + mg_printf(connection, " Average Wait Lock Time/Voxel: %s usecs\r\n", + locale.toString((uint)averageLockWaitTimePerVoxel).rightJustified(COLUMN_WIDTH, ' ').toLocal8Bit().constData()); + + } + + mg_printf(connection, "%s", "\r\n"); mg_printf(connection, "%s", "\r\n"); diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index 9d3ffcdc51..66c0d13397 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -34,6 +34,8 @@ void VoxelServerPacketProcessor::resetStats() { _totalLockWaitTime = 0; _totalVoxelsInPacket = 0; _totalPackets = 0; + + _singleSenderStats.clear(); } @@ -214,5 +216,36 @@ void VoxelServerPacketProcessor::trackInboudPackets(const QUuid& nodeUUID, int s _totalLockWaitTime += lockWaitTime; _totalVoxelsInPacket += voxelsInPacket; _totalPackets++; + + // find the individual senders stats and track them there too... + // see if this is the first we've heard of this node... + if (_singleSenderStats.find(nodeUUID) == _singleSenderStats.end()) { + SingleSenderStats stats; + + stats._totalTransitTime += transitTime; + stats._totalProcessTime += processTime; + stats._totalLockWaitTime += lockWaitTime; + stats._totalVoxelsInPacket += voxelsInPacket; + stats._totalPackets++; + + _singleSenderStats[nodeUUID] = stats; + } else { + SingleSenderStats& stats = _singleSenderStats[nodeUUID]; + stats._totalTransitTime += transitTime; + stats._totalProcessTime += processTime; + stats._totalLockWaitTime += lockWaitTime; + stats._totalVoxelsInPacket += voxelsInPacket; + stats._totalPackets++; + } } + +SingleSenderStats::SingleSenderStats() { + _totalTransitTime = 0; + _totalProcessTime = 0; + _totalLockWaitTime = 0; + _totalVoxelsInPacket = 0; + _totalPackets = 0; +} + + diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h index b461c5a664..8c7dc4837f 100644 --- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h @@ -11,9 +11,36 @@ #ifndef __voxel_server__VoxelServerPacketProcessor__ #define __voxel_server__VoxelServerPacketProcessor__ +#include + #include class VoxelServer; +class SingleSenderStats { +public: + SingleSenderStats(); + + uint64_t getAverateTransitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalTransitTime / _totalPackets; } + uint64_t getAverageProcessTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalProcessTime / _totalPackets; } + uint64_t getAverageLockWaitTimePerPacket() const { return _totalPackets == 0 ? 0 : _totalLockWaitTime / _totalPackets; } + uint64_t getTotalVoxelsProcessed() const { return _totalVoxelsInPacket; } + uint64_t getTotalPacketsProcessed() const { return _totalPackets; } + uint64_t getAverageProcessTimePerVoxel() const + { return _totalVoxelsInPacket == 0 ? 0 : _totalProcessTime / _totalVoxelsInPacket; } + uint64_t getAverageLockWaitTimePerVoxel() const + { return _totalVoxelsInPacket == 0 ? 0 : _totalLockWaitTime / _totalVoxelsInPacket; } + + uint64_t _totalTransitTime; + uint64_t _totalProcessTime; + uint64_t _totalLockWaitTime; + uint64_t _totalVoxelsInPacket; + uint64_t _totalPackets; +}; + +typedef std::map NodeToSenderStatsMap; +typedef std::map::iterator NodeToSenderStatsMapIterator; + + /// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() class VoxelServerPacketProcessor : public ReceivedPacketProcessor { @@ -33,6 +60,8 @@ public: void resetStats(); + NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; } + protected: virtual void processPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength); @@ -49,5 +78,6 @@ private: uint64_t _totalVoxelsInPacket; uint64_t _totalPackets; + NodeToSenderStatsMap _singleSenderStats; }; #endif // __voxel_server__VoxelServerPacketProcessor__ From 59cfa89f1be052aa01c50d9d1db927274a1fcb92 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 11 Nov 2013 17:26:04 -0800 Subject: [PATCH 3/4] fixed CR feedback --- .../voxel-server-library/src/VoxelServer.cpp | 56 ++++++++++--------- .../src/VoxelServerPacketProcessor.cpp | 4 +- .../src/VoxelServerPacketProcessor.h | 2 +- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 11d7d3ff1c..31f856ab86 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -115,6 +115,8 @@ void VoxelServer::initMongoose(int port) { int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { const struct mg_request_info* ri = mg_get_request_info(connection); + + VoxelServer* theServer = GetInstance(); #ifdef FORCE_CRASH if (strcmp(ri->uri, "/force_crash") == 0 && strcmp(ri->request_method, "GET") == 0) { @@ -135,7 +137,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { } if (strcmp(ri->uri, "/resetStats") == 0 && strcmp(ri->request_method, "GET") == 0) { - GetInstance()->_voxelServerPacketProcessor->resetStats(); + theServer->_voxelServerPacketProcessor->resetStats(); showStats = true; } @@ -148,14 +150,14 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { mg_printf(connection, "%s", "
\r\n");
         mg_printf(connection, "%s", "Your Voxel Server is running... [RELOAD]\r\n");
 
-        tm* localtm = localtime(&GetInstance()->_started);
+        tm* localtm = localtime(&theServer->_started);
         const int MAX_TIME_LENGTH = 128;
         char buffer[MAX_TIME_LENGTH];
         strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", localtm);
         mg_printf(connection, "Running since: %s", buffer);
 
         // Convert now to tm struct for UTC
-        tm* gmtm = gmtime(&GetInstance()->_started);
+        tm* gmtm = gmtime(&theServer->_started);
         if (gmtm != NULL) {
             strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", gmtm);
             mg_printf(connection, " [%s UTM] ", buffer);
@@ -164,7 +166,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
 
         uint64_t now  = usecTimestampNow();
         const int USECS_PER_MSEC = 1000;
-        uint64_t msecsElapsed = (now - GetInstance()->_startedUSecs) / USECS_PER_MSEC;
+        uint64_t msecsElapsed = (now - theServer->_startedUSecs) / USECS_PER_MSEC;
         const int MSECS_PER_SEC = 1000;
         const int SECS_PER_MIN = 60;
         const int MIN_PER_HOUR = 60;
@@ -189,15 +191,15 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
 
 
         // display voxel file load time
-        if (GetInstance()->isInitialLoadComplete()) {
-            tm* voxelsLoadedAtLocal = localtime(GetInstance()->getLoadCompleted());
+        if (theServer->isInitialLoadComplete()) {
+            tm* voxelsLoadedAtLocal = localtime(theServer->getLoadCompleted());
             const int MAX_TIME_LENGTH = 128;
             char buffer[MAX_TIME_LENGTH];
             strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtLocal);
             mg_printf(connection, "Voxels Loaded At: %s", buffer);
 
             // Convert now to tm struct for UTC
-            tm* voxelsLoadedAtUTM = gmtime(GetInstance()->getLoadCompleted());
+            tm* voxelsLoadedAtUTM = gmtime(theServer->getLoadCompleted());
             if (gmtm != NULL) {
                 strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtUTM);
                 mg_printf(connection, " [%s UTM] ", buffer);
@@ -205,7 +207,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
             mg_printf(connection, "%s", "\r\n");
 
 
-            uint64_t msecsElapsed = GetInstance()->getLoadElapsedTime() / USECS_PER_MSEC;;
+            uint64_t msecsElapsed = theServer->getLoadElapsedTime() / USECS_PER_MSEC;;
             float seconds = (msecsElapsed % MSECS_PER_MIN)/(float)MSECS_PER_SEC;
             int minutes = (msecsElapsed/(MSECS_PER_MIN)) % MIN_PER_HOUR;
             int hours = (msecsElapsed/(MSECS_PER_MIN * MIN_PER_HOUR));
@@ -232,8 +234,8 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
 
         mg_printf(connection, "%s", "Configuration:\r\n");
 
-        for (int i = 1; i < GetInstance()->_argc; i++) {
-            mg_printf(connection, "%s ", GetInstance()->_argv[i]);
+        for (int i = 1; i < theServer->_argc; i++) {
+            mg_printf(connection, "%s ", theServer->_argv[i]);
         }
         mg_printf(connection, "%s", "\r\n"); // one to end the config line
         mg_printf(connection, "%s", "\r\n"); // two more for spacing
@@ -251,22 +253,22 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
                     locale.toString((uint)nodeCount).rightJustified(16, ' ').toLocal8Bit().constData());
         mg_printf(connection, "    Internal Nodes: %s nodes (%5.2f%%)\r\n",
             locale.toString((uint)internalNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
-            ((float)internalNodeCount/(float)nodeCount) * AS_PERCENT);
+            ((float)internalNodeCount / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "        Leaf Nodes: %s nodes (%5.2f%%)\r\n", 
             locale.toString((uint)leafNodeCount).rightJustified(16, ' ').toLocal8Bit().constData(),
-            ((float)leafNodeCount/(float)nodeCount) * AS_PERCENT);
+            ((float)leafNodeCount / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "%s", "\r\n");
         mg_printf(connection, "%s", "\r\n");
 
         // display inbound packet stats
         mg_printf(connection, "%s", "Voxel Edit Statistics... [RESET]\r\n");
-        uint64_t averageTransitTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverateTransitTimePerPacket();
-        uint64_t averageProcessTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverageProcessTimePerPacket();
-        uint64_t averageLockWaitTimePerPacket = GetInstance()->_voxelServerPacketProcessor->getAverageLockWaitTimePerPacket();
-        uint64_t averageProcessTimePerVoxel = GetInstance()->_voxelServerPacketProcessor->getAverageProcessTimePerVoxel();
-        uint64_t averageLockWaitTimePerVoxel = GetInstance()->_voxelServerPacketProcessor->getAverageLockWaitTimePerVoxel();
-        uint64_t totalVoxelsProcessed = GetInstance()->_voxelServerPacketProcessor->getTotalVoxelsProcessed();
-        uint64_t totalPacketsProcessed = GetInstance()->_voxelServerPacketProcessor->getTotalPacketsProcessed();
+        uint64_t averageTransitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverateTransitTimePerPacket();
+        uint64_t averageProcessTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerPacket();
+        uint64_t averageLockWaitTimePerPacket = theServer->_voxelServerPacketProcessor->getAverageLockWaitTimePerPacket();
+        uint64_t averageProcessTimePerVoxel = theServer->_voxelServerPacketProcessor->getAverageProcessTimePerVoxel();
+        uint64_t averageLockWaitTimePerVoxel = theServer->_voxelServerPacketProcessor->getAverageLockWaitTimePerVoxel();
+        uint64_t totalVoxelsProcessed = theServer->_voxelServerPacketProcessor->getTotalVoxelsProcessed();
+        uint64_t totalPacketsProcessed = theServer->_voxelServerPacketProcessor->getTotalPacketsProcessed();
 
         float averageVoxelsPerPacket = totalPacketsProcessed == 0 ? 0 : totalVoxelsProcessed / totalPacketsProcessed;
 
@@ -289,7 +291,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
 
 
         int senderNumber = 0;
-        NodeToSenderStatsMap& allSenderStats = GetInstance()->_voxelServerPacketProcessor->getSingleSenderStats();
+        NodeToSenderStatsMap& allSenderStats = theServer->_voxelServerPacketProcessor->getSingleSenderStats();
         for (NodeToSenderStatsMapIterator i = allSenderStats.begin(); i != allSenderStats.end(); i++) {
             senderNumber++;
             // iterator->first = key
@@ -364,7 +366,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
             checkSum += VoxelNode::getChildrenCount(i);
             mg_printf(connection, "    Nodes with %d children:      %s nodes (%5.2f%%)\r\n", i, 
                 locale.toString((uint)VoxelNode::getChildrenCount(i)).rightJustified(16, ' ').toLocal8Bit().constData(),
-                ((float)VoxelNode::getChildrenCount(i)/(float)nodeCount) * AS_PERCENT);
+                ((float)VoxelNode::getChildrenCount(i) / (float)nodeCount) * AS_PERCENT);
         }
         mg_printf(connection, "%s", "                                ----------------------\r\n");
         mg_printf(connection, "                    Total:      %s nodes\r\n", 
@@ -375,22 +377,22 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
         mg_printf(connection, "%s", "VoxelNode Children Encoding Statistics...\r\n");
         
         mg_printf(connection, "    Single or No Children:      %10.llu nodes (%5.2f%%)\r\n",
-            VoxelNode::getSingleChildrenCount(), ((float)VoxelNode::getSingleChildrenCount()/(float)nodeCount) * AS_PERCENT);
+            VoxelNode::getSingleChildrenCount(), ((float)VoxelNode::getSingleChildrenCount() / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "    Two Children as Offset:     %10.llu nodes (%5.2f%%)\r\n", 
             VoxelNode::getTwoChildrenOffsetCount(), 
-            ((float)VoxelNode::getTwoChildrenOffsetCount()/(float)nodeCount) * AS_PERCENT);
+            ((float)VoxelNode::getTwoChildrenOffsetCount() / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "    Two Children as External:   %10.llu nodes (%5.2f%%)\r\n", 
             VoxelNode::getTwoChildrenExternalCount(), 
-            ((float)VoxelNode::getTwoChildrenExternalCount()/(float)nodeCount) * AS_PERCENT);
+            ((float)VoxelNode::getTwoChildrenExternalCount() / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "    Three Children as Offset:   %10.llu nodes (%5.2f%%)\r\n", 
             VoxelNode::getThreeChildrenOffsetCount(), 
-            ((float)VoxelNode::getThreeChildrenOffsetCount()/(float)nodeCount) * AS_PERCENT);
+            ((float)VoxelNode::getThreeChildrenOffsetCount() / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "    Three Children as External: %10.llu nodes (%5.2f%%)\r\n", 
             VoxelNode::getThreeChildrenExternalCount(), 
-            ((float)VoxelNode::getThreeChildrenExternalCount()/(float)nodeCount) * AS_PERCENT);
+            ((float)VoxelNode::getThreeChildrenExternalCount() / (float)nodeCount) * AS_PERCENT);
         mg_printf(connection, "    Children as External Array: %10.llu nodes (%5.2f%%)\r\n",
             VoxelNode::getExternalChildrenCount(), 
-            ((float)VoxelNode::getExternalChildrenCount()/(float)nodeCount) * AS_PERCENT);
+            ((float)VoxelNode::getExternalChildrenCount() / (float)nodeCount) * AS_PERCENT);
 
         checkSum = VoxelNode::getSingleChildrenCount() +
                             VoxelNode::getTwoChildrenOffsetCount() + VoxelNode::getTwoChildrenExternalCount() + 
diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp
index 66c0d13397..2581c923f5 100644
--- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp
+++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp
@@ -148,7 +148,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
                 qDebug() << "sender has no known nodeUUID.\n";
             }
         }
-        trackInboudPackets(nodeUUID, sequence, transitTime, voxelsInPacket, processTime, lockWaitTime);
+        trackInboundPackets(nodeUUID, sequence, transitTime, voxelsInPacket, processTime, lockWaitTime);
 
     } else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) {
 
@@ -208,7 +208,7 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
     }
 }
 
-void VoxelServerPacketProcessor::trackInboudPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, 
+void VoxelServerPacketProcessor::trackInboundPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, 
             int voxelsInPacket, uint64_t processTime, uint64_t lockWaitTime) {
             
     _totalTransitTime += transitTime;
diff --git a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h
index 8c7dc4837f..108e101417 100644
--- a/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h
+++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h
@@ -66,7 +66,7 @@ protected:
     virtual void processPacket(sockaddr& senderAddress, unsigned char*  packetData, ssize_t packetLength);
 
 private:
-    void trackInboudPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, 
+    void trackInboundPackets(const QUuid& nodeUUID, int sequence, uint64_t transitTime, 
             int voxelsInPacket, uint64_t processTime, uint64_t lockWaitTime);
 
     VoxelServer* _myServer;

From c625d79fd26f5fa0f9e2ee7addf07ced32bf0bb8 Mon Sep 17 00:00:00 2001
From: ZappoMan 
Date: Mon, 11 Nov 2013 17:27:29 -0800
Subject: [PATCH 4/4] removed comment

---
 libraries/voxel-server-library/src/VoxelServer.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp
index 31f856ab86..1952ede7d8 100644
--- a/libraries/voxel-server-library/src/VoxelServer.cpp
+++ b/libraries/voxel-server-library/src/VoxelServer.cpp
@@ -294,8 +294,6 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
         NodeToSenderStatsMap& allSenderStats = theServer->_voxelServerPacketProcessor->getSingleSenderStats();
         for (NodeToSenderStatsMapIterator i = allSenderStats.begin(); i != allSenderStats.end(); i++) {
             senderNumber++;
-            // iterator->first = key
-            // iterator->second = value
             QUuid senderID = i->first;
             SingleSenderStats& senderStats = i->second;