From 8d7874b01bc4a1201303698f7489c9239f680f41 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 17 Oct 2013 13:47:18 -0700 Subject: [PATCH] add guards to prevent runaway reaverageVoxels(), added stats to see if 4 children could be packed internally --- .../src/VoxelPersistThread.cpp | 13 ++++++-- .../voxel-server-library/src/VoxelServer.cpp | 9 +++++- libraries/voxels/src/VoxelNode.cpp | 31 ++++++++++++++++++- libraries/voxels/src/VoxelNode.h | 8 ++++- libraries/voxels/src/VoxelTree.cpp | 16 +++++++++- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/libraries/voxel-server-library/src/VoxelPersistThread.cpp b/libraries/voxel-server-library/src/VoxelPersistThread.cpp index 55dce2ed9b..75954aacec 100644 --- a/libraries/voxel-server-library/src/VoxelPersistThread.cpp +++ b/libraries/voxel-server-library/src/VoxelPersistThread.cpp @@ -29,13 +29,20 @@ bool VoxelPersistThread::process() { _initialLoad = true; qDebug("loading voxels from file: %s...\n", _filename); - bool persistantFileRead = _tree->readFromSVOFile(_filename); + bool persistantFileRead; + + { + PerformanceWarning warn(true, "Loading Voxel File", true); + persistantFileRead = _tree->readFromSVOFile(_filename); + } + if (persistantFileRead) { - PerformanceWarning warn(true, "reaverageVoxelColors()", true); + PerformanceWarning warn(true, "Voxels Re-Averaging", true); // after done inserting all these voxels, then reaverage colors + qDebug("BEGIN Voxels Re-Averaging\n"); _tree->reaverageVoxelColors(_tree->rootNode); - qDebug("Voxels reAveraged\n"); + qDebug("DONE WITH Voxels Re-Averaging\n"); } _tree->clearDirtyBit(); // the tree is clean since we just loaded it diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index e3c120d0bb..0983abffb8 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -186,7 +186,7 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { mg_printf(connection, "%s", " ----------------\r\n"); mg_printf(connection, " Total: %10.llu nodes\r\n", checkSum); mg_printf(connection, " Expected: %10.lu nodes\r\n", nodeCount); - + mg_printf(connection, "%s", "\r\n"); mg_printf(connection, "%s", "VoxelNode Children Population Statistics...\r\n"); checkSum = 0; @@ -198,6 +198,13 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) { mg_printf(connection, "%s", " ----------------\r\n"); mg_printf(connection, " Total: %10.llu nodes\r\n", checkSum); + mg_printf(connection, "%s", "\r\n"); + mg_printf(connection, "%s", "In other news....\r\n"); + mg_printf(connection, "could store 4 children internally: %10.llu nodes\r\n", + VoxelNode::getCouldStoreFourChildrenInternally()); + mg_printf(connection, "could NOT store 4 children internally: %10.llu nodes\r\n", + VoxelNode::getCouldNotStoreFourChildrenInternally()); + return 1; } else { // have mongoose process this request from the document_root diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index dc29c57f19..39099b44ba 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -271,6 +271,8 @@ uint64_t VoxelNode::_threeChildrenOffsetCount = 0; uint64_t VoxelNode::_threeChildrenExternalCount = 0; uint64_t VoxelNode::_externalChildrenCount = 0; uint64_t VoxelNode::_childrenCount[NUMBER_OF_CHILDREN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +uint64_t VoxelNode::_couldStoreFourChildrenInternally = 0; +uint64_t VoxelNode::_couldNotStoreFourChildrenInternally = 0; VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { PerformanceWarning warn(false,"getChildAtIndex",false,&_getChildAtIndexTime,&_getChildAtIndexCalls); @@ -531,6 +533,27 @@ void VoxelNode::retrieveThreeChildren(VoxelNode*& childOne, VoxelNode*& childTwo _threeChildrenOffsetCount--; } } + +void VoxelNode::checkStoreFourChildren(VoxelNode* childOne, VoxelNode* childTwo, VoxelNode* childThree, VoxelNode* childFour) { + int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this; + int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this; + int64_t offsetThree = (uint8_t*)childThree - (uint8_t*)this; + int64_t offsetFour = (uint8_t*)childFour - (uint8_t*)this; + + const int64_t minOffset = std::numeric_limits::min(); + const int64_t maxOffset = std::numeric_limits::max(); + + if (isBetween(offsetOne, maxOffset, minOffset) && + isBetween(offsetTwo, maxOffset, minOffset) && + isBetween(offsetThree, maxOffset, minOffset) && + isBetween(offsetFour, maxOffset, minOffset) + ) { + _couldStoreFourChildrenInternally++; + } else { + _couldNotStoreFourChildrenInternally++; + } +} + void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { PerformanceWarning warn(false,"setChildAtIndex",false,&_setChildAtIndexTime,&_setChildAtIndexCalls); @@ -750,7 +773,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { const int newChildCount = 4; _children.external = new VoxelNode*[newChildCount]; _externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*); - + _children.external[0] = childOne; _children.external[1] = childTwo; _children.external[2] = childThree; @@ -866,6 +889,12 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { qDebug("THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d\n",previousChildCount, newChildCount); } + // check to see if we could store these 4 children locally + if (getChildCount() == 4 && _childrenExternal && _children.external) { + checkStoreFourChildren(_children.external[0], _children.external[1], _children.external[2], _children.external[3]); + } + + #ifdef HAS_AUDIT_CHILDREN _childrenArray[childIndex] = child; auditChildren("setChildAtIndex()"); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 847d74e550..1734bb5c87 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -131,7 +131,9 @@ public: static uint64_t getThreeChildrenExternalCount() { return _threeChildrenExternalCount; } static uint64_t getExternalChildrenCount() { return _externalChildrenCount; } static uint64_t getChildrenCount(int childCount) { return _childrenCount[childCount]; } - + + static uint64_t getCouldStoreFourChildrenInternally() { return _couldStoreFourChildrenInternally; } + static uint64_t getCouldNotStoreFourChildrenInternally() { return _couldNotStoreFourChildrenInternally; } #ifdef HAS_AUDIT_CHILDREN void auditChildren(const char* label) const; @@ -145,6 +147,7 @@ private: void retrieveThreeChildren(VoxelNode*& childOne, VoxelNode*& childTwo, VoxelNode*& childThree); void decodeThreeOffsets(int64_t& offsetOne, int64_t& offsetTwo, int64_t& offsetThree) const; void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree); + void checkStoreFourChildren(VoxelNode* childOne, VoxelNode* childTwo, VoxelNode* childThree, VoxelNode* childFour); void calculateAABox(); void init(unsigned char * octalCode); @@ -221,6 +224,9 @@ private: static uint64_t _threeChildrenExternalCount; static uint64_t _externalChildrenCount; static uint64_t _childrenCount[NUMBER_OF_CHILDREN + 1]; + + static uint64_t _couldStoreFourChildrenInternally; + static uint64_t _couldNotStoreFourChildrenInternally; }; #endif /* defined(__hifi__VoxelNode__) */ \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index e4a142306d..3911560f66 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -630,9 +630,22 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { } // Note: this is an expensive call. Don't call it unless you really need to reaverage the entire tree (from startNode) -void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) { +void VoxelTree::reaverageVoxelColors(VoxelNode* startNode) { // if our tree is a reaveraging tree, then we do this, otherwise we don't do anything if (_shouldReaverage) { + static int recursionCount; + if (startNode == rootNode) { + recursionCount = 0; + } else { + recursionCount++; + } + const int UNREASONABLY_DEEP_RECURSION = 20; + if (recursionCount > UNREASONABLY_DEEP_RECURSION) { + qDebug("VoxelTree::reaverageVoxelColors()... bailing out of UNREASONABLY_DEEP_RECURSION\n"); + recursionCount--; + return; + } + bool hasChildren = false; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { @@ -647,6 +660,7 @@ void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) { if (hasChildren && !startNode->collapseIdenticalLeaves()) { startNode->setColorFromAverageOfChildren(); } + recursionCount--; } }