Avoid OOM diring HTML parsing by reducing max block size and freeing unneeded buffers
This commit is contained in:
@@ -355,12 +355,19 @@ void ParsedText::layoutAndExtractLines(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove consumed words so size() reflects only remaining words
|
// Remove consumed words so size() reflects only remaining words, then
|
||||||
|
// release excess capacity. Without shrink_to_fit the vector retains a
|
||||||
|
// large allocation from before the flush; the next paragraph fills it
|
||||||
|
// back up and eventually needs an even larger contiguous realloc.
|
||||||
if (lineCount > 0) {
|
if (lineCount > 0) {
|
||||||
const size_t consumed = lineBreakIndices[lineCount - 1];
|
const size_t consumed = lineBreakIndices[lineCount - 1];
|
||||||
words.erase(words.begin(), words.begin() + consumed);
|
words.erase(words.begin(), words.begin() + consumed);
|
||||||
wordStyles.erase(wordStyles.begin(), wordStyles.begin() + consumed);
|
wordStyles.erase(wordStyles.begin(), wordStyles.begin() + consumed);
|
||||||
wordContinues.erase(wordContinues.begin(), wordContinues.begin() + consumed);
|
wordContinues.erase(wordContinues.begin(), wordContinues.begin() + consumed);
|
||||||
|
words.shrink_to_fit();
|
||||||
|
wordStyles.shrink_to_fit();
|
||||||
|
wordContinues.shrink_to_fit();
|
||||||
|
isContinuation_ = !includeLastLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1207,11 +1207,12 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
|||||||
self->partWordBuffer[self->partWordBufferIndex++] = s[i];
|
self->partWordBuffer[self->partWordBufferIndex++] = s[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have > 750 words buffered up, perform the layout and consume out all but the last line
|
// Flush when words approach the doubling boundary that would require a
|
||||||
// There should be enough here to build out 1-2 full pages and doing this will free up a lot of
|
// large contiguous realloc. 96 fires before capacity reaches 128
|
||||||
// memory.
|
// (the next doubling after 64), keeping the realloc below 1.5KB and
|
||||||
// Spotted when reading Intermezzo, there are some really long text blocks in there.
|
// releasing excess capacity via shrink_to_fit in layoutAndExtractLines.
|
||||||
if (self->currentTextBlock->size() > 750) {
|
// The original 750-word threshold was too late for low-heap devices.
|
||||||
|
if (self->currentTextBlock->size() > 96) {
|
||||||
LOG_DBG("EHP", "Text block too long, splitting into multiple pages");
|
LOG_DBG("EHP", "Text block too long, splitting into multiple pages");
|
||||||
const int horizontalInset = self->currentTextBlock->getBlockStyle().totalHorizontalInset();
|
const int horizontalInset = self->currentTextBlock->getBlockStyle().totalHorizontalInset();
|
||||||
const uint16_t effectiveWidth = (horizontalInset < self->viewportWidth)
|
const uint16_t effectiveWidth = (horizontalInset < self->viewportWidth)
|
||||||
|
|||||||
Reference in New Issue
Block a user