Limit how many reads we defer to avoid overflowing the cache

This commit is contained in:
David Schwartz
2014-03-07 14:15:04 -08:00
committed by Nik Bougalis
parent 163daf012a
commit b4593a274d
3 changed files with 36 additions and 4 deletions

View File

@@ -132,14 +132,18 @@ void SHAMap::getMissingNodes (std::vector<SHAMapNode>& nodeIDs, std::vector<uint
return;
}
int const maxDefer = getApp().getNodeStore().getDesiredAsyncReadCount ();
// Track the missing hashes we have found so far
std::set <uint256> missingHashes;
while (1)
{
std::vector <std::pair <SHAMapNode, uint256>> deferredReads;
deferredReads.reserve (maxDefer + 16);
std::stack <GMNEntry> stack;
int deferCount = 0;
// Traverse the map without blocking
@@ -179,7 +183,7 @@ void SHAMap::getMissingNodes (std::vector<SHAMapNode>& nodeIDs, std::vector<uint
else
{
// read is deferred
++deferCount;
deferredReads.emplace_back (childID, childHash);
}
fullBelow = false; // This node is not known full below
@@ -220,13 +224,30 @@ void SHAMap::getMissingNodes (std::vector<SHAMapNode>& nodeIDs, std::vector<uint
}
}
while (node != NULL);
while ((node != NULL) && (deferredReads.size () <= maxDefer));
// If we didn't defer any reads, we're done
if (deferCount == 0)
if (deferredReads.empty ())
break;
getApp().getNodeStore().waitReads();
// Process all deferred reads
for (auto const& node : deferredReads)
{
auto const& nodeID = node.first;
auto const& nodeHash = node.second;
SHAMapNode *nodePtr = getNodePointerNT (nodeID, nodeHash, filter);
if (!nodePtr && missingHashes.insert (nodeHash).second)
{
nodeIDs.push_back (nodeID);
hashes.push_back (nodeHash);
if (--max <= 0)
return;
}
}
}
if (nodeIDs.empty ())

View File

@@ -79,6 +79,11 @@ public:
*/
virtual void waitReads () = 0;
/** Get the maximum number of async reads the node store prefers.
@return The number of async reads preferred.
*/
virtual int getDesiredAsyncReadCount () = 0;
/** Store the object.
The caller's Blob parameter is overwritten.

View File

@@ -126,6 +126,12 @@ public:
}
int getDesiredAsyncReadCount ()
{
// We prefer a client not fill our cache
return m_cache.getTargetSize() / 4;
}
NodeObject::Ptr fetch (uint256 const& hash)
{
// See if the object already exists in the cache