From 32bfa55d981909f764720120dcbb5a2426ad9873 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 26 Jul 2018 13:10:43 +0200 Subject: [PATCH] Attempt to estimate the minimum required `buffer` length when initializing `StreamsSequenceStream` instances For most other `DecodeStream` based streams, we'll attempt to estimate the minimum `buffer` length based on the raw stream data. The purpose of this is to avoid having to unnecessarily re-size the `buffer`, thus reducing the number of *intermediate* allocations necessary when decoding the stream data. However, currently no such optimization is attempted for `StreamsSequenceStream`, and given that they can often be quite large that seems unfortunate. To improve this, at least somewhat, this patch utilizes the raw sizes of the `StreamsSequenceStream` sub-streams to estimate the minimum required `buffer` length. Most likely this patch won't have a huge effect on memory consumption, however for pathological cases it should help reduce peak memory usage slightly. One example is the PDF file in issue 2813, where currently the `StreamsSequenceStream` instances would grow their `buffer`s as `2 MiB -> 4 MiB -> 8 MiB -> 16 MiB -> 32 MiB`. With this patch, the same stream `buffers`s grow as `8 MiB -> 16 MiB -> 32 MiB`, thus avoiding a total of `12 MiB` of *intermediate* allocations (since there's two `StreamsSequenceStream` used, for rendering/text-extraction). --- src/core/stream.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/stream.js b/src/core/stream.js index eefb04d46..fa89207dc 100644 --- a/src/core/stream.js +++ b/src/core/stream.js @@ -126,6 +126,8 @@ var DecodeStream = (function DecodeStreamClosure() { var emptyBuffer = new Uint8Array(0); function DecodeStream(maybeMinBufferLength) { + this._rawMinBufferLength = maybeMinBufferLength || 0; + this.pos = 0; this.bufferLength = 0; this.eof = false; @@ -251,7 +253,17 @@ var DecodeStream = (function DecodeStreamClosure() { var StreamsSequenceStream = (function StreamsSequenceStreamClosure() { function StreamsSequenceStream(streams) { this.streams = streams; - DecodeStream.call(this, /* maybeLength = */ null); + + let maybeLength = 0; + for (let i = 0, ii = streams.length; i < ii; i++) { + const stream = streams[i]; + if (stream instanceof DecodeStream) { + maybeLength += stream._rawMinBufferLength; + } else { + maybeLength += stream.length; + } + } + DecodeStream.call(this, maybeLength); } StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);