Improve how DecodeStream handles empty buffers.

DecodeStream currently initializes its |buffer| field to |null|, which
is reasonable, because lots of DecodeStreams never need to instantiate a
buffer. But this requires various special cases in the code.

This patch change it so DecodeStreamClosure has a single empty
Uint8Array which gets shared between all buffers upon initialization.
This avoids the special cases.

DecodeStream.prototype.ensureBuffer() is really hot, and this removes a
test from the fast path. For one 226 page scanned document this sped up
rendering by about 2%.
This commit is contained in:
Nicholas Nethercote 2014-07-02 18:39:23 -07:00
parent 2e98f9095e
commit db866945b7

View File

@ -116,11 +116,17 @@ var StringStream = (function StringStreamClosure() {
// super class for the decoding streams // super class for the decoding streams
var DecodeStream = (function DecodeStreamClosure() { var DecodeStream = (function DecodeStreamClosure() {
// Lots of DecodeStreams are created whose buffers are never used. For these
// we share a single empty buffer. This is (a) space-efficient and (b) avoids
// having special cases that would be required if we used |null| for an empty
// buffer.
var emptyBuffer = new Uint8Array(0);
function DecodeStream(maybeMinBufferLength) { function DecodeStream(maybeMinBufferLength) {
this.pos = 0; this.pos = 0;
this.bufferLength = 0; this.bufferLength = 0;
this.eof = false; this.eof = false;
this.buffer = null; this.buffer = emptyBuffer;
this.minBufferLength = 512; this.minBufferLength = 512;
if (maybeMinBufferLength) { if (maybeMinBufferLength) {
// Compute the first power of two that is as big as maybeMinBufferLength. // Compute the first power of two that is as big as maybeMinBufferLength.
@ -139,23 +145,15 @@ var DecodeStream = (function DecodeStreamClosure() {
}, },
ensureBuffer: function DecodeStream_ensureBuffer(requested) { ensureBuffer: function DecodeStream_ensureBuffer(requested) {
var buffer = this.buffer; var buffer = this.buffer;
var current; if (requested <= buffer.byteLength) {
if (buffer) {
current = buffer.byteLength;
if (requested <= current) {
return buffer; return buffer;
} }
} else {
current = 0;
}
var size = this.minBufferLength; var size = this.minBufferLength;
while (size < requested) { while (size < requested) {
size *= 2; size *= 2;
} }
var buffer2 = new Uint8Array(size); var buffer2 = new Uint8Array(size);
if (buffer) {
buffer2.set(buffer); buffer2.set(buffer);
}
return (this.buffer = buffer2); return (this.buffer = buffer2);
}, },
getByte: function DecodeStream_getByte() { getByte: function DecodeStream_getByte() {
@ -199,12 +197,6 @@ var DecodeStream = (function DecodeStreamClosure() {
this.readBlock(); this.readBlock();
} }
end = this.bufferLength; end = this.bufferLength;
// checking if bufferLength is still 0 then
// the buffer has to be initialized
if (!end) {
this.buffer = new Uint8Array(0);
}
} }
this.pos = end; this.pos = end;