From a916d0398ac10489e9b382c6ad6f066999310254 Mon Sep 17 00:00:00 2001 From: James Wahlin Date: Wed, 14 Dec 2016 16:20:26 -0500 Subject: SERVER-27288 Release Document ref in DocumentSourceSkip and DocumentSourceMatch getNext() --- src/mongo/db/pipeline/document_source_skip.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/mongo/db/pipeline/document_source_skip.cpp') diff --git a/src/mongo/db/pipeline/document_source_skip.cpp b/src/mongo/db/pipeline/document_source_skip.cpp index ff528f0634e..114a2f7d1b4 100644 --- a/src/mongo/db/pipeline/document_source_skip.cpp +++ b/src/mongo/db/pipeline/document_source_skip.cpp @@ -57,11 +57,20 @@ const char* DocumentSourceSkip::getSourceName() const { DocumentSource::GetNextResult DocumentSourceSkip::getNext() { pExpCtx->checkForInterrupt(); - auto nextInput = pSource->getNext(); - for (; _nSkippedSoFar < _nToSkip && nextInput.isAdvanced(); nextInput = pSource->getNext()) { + while (_nSkippedSoFar < _nToSkip) { + // For performance reasons, a streaming stage must not keep references to documents across + // calls to getNext(). Such stages must retrieve a result from their child and then release + // it (or return it) before asking for another result. Failing to do so can result in extra + // work, since the Document/Value library must copy data on write when that data has a + // refcount above one. + auto nextInput = pSource->getNext(); + if (!nextInput.isAdvanced()) { + return nextInput; + } ++_nSkippedSoFar; } - return nextInput; + + return pSource->getNext(); } Value DocumentSourceSkip::serialize(bool explain) const { -- cgit v1.2.1