Reduce the number of function calls in the Dict class

The following changes were made:
 - Remove unnecessary `typeof` checks in the `get`/`getAsync` methods.
 - Reduce unnecessary code duplication in the `get`/`getAsync` methods.
 - Inline the `Ref` checks in the `get`/`getAsync`/`getArray` methods, since it helps avoid many unnecessary functions calls. I.e. this way it's possible to directly call `XRef.{fetch, fetchAsync)` only when necessary, rather than always having to call `XRef.{fetchIfRef, fetchIfRefAsync)`.

This patch was tested using the PDF file from issue 2618, i.e. http://bugzilla-attachments.gnome.org/attachment.cgi?id=226471, using the following manifest file:
```
[
    {  "id": "issue2618",
       "file": "../web/pdfs/issue2618.pdf",
       "md5": "",
       "rounds": 250,
       "type": "eq"
    }
]
```
This gave the following results when comparing this patch against the `master` branch:
```
-- Grouped By browser, stat --
browser | stat         | Count | Baseline(ms) | Current(ms) | +/- |    %  | Result(P<.05)
------- | ------------ | ----- | ------------ | ----------- | --- | ----- | -------------
Firefox | Overall      |   250 |         2821 |        2790 | -32 | -1.12 |        faster
Firefox | Page Request |   250 |            2 |           2 |   0 |  6.68 |
Firefox | Rendering    |   250 |         2820 |        2788 | -32 | -1.13 |        faster
```
This commit is contained in:
Jonas Jenwald 2019-09-22 13:16:38 +02:00
parent 44f4cd529d
commit 2cac68467f

View File

@ -81,59 +81,47 @@ var Dict = (function DictClosure() {
}, },
// automatically dereferences Ref objects // automatically dereferences Ref objects
get: function Dict_get(key1, key2, key3) { get(key1, key2, key3) {
var value; let value = this._map[key1];
var xref = this.xref, suppressEncryption = this.suppressEncryption; if (value === undefined && !(key1 in this._map) && key2 !== undefined) {
if (typeof (value = this._map[key1]) !== 'undefined' || value = this._map[key2];
key1 in this._map || typeof key2 === 'undefined') { if (value === undefined && !(key2 in this._map) && key3 !== undefined) {
return xref ? xref.fetchIfRef(value, suppressEncryption) : value; value = this._map[key3];
}
} }
if (typeof (value = this._map[key2]) !== 'undefined' || if (value instanceof Ref && this.xref) {
key2 in this._map || typeof key3 === 'undefined') { return this.xref.fetch(value, this.suppressEncryption);
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
} }
value = this._map[key3]; return value;
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
}, },
// Same as get(), but returns a promise and uses fetchIfRefAsync(). // Same as get(), but returns a promise and uses fetchIfRefAsync().
getAsync: function Dict_getAsync(key1, key2, key3) { async getAsync(key1, key2, key3) {
var value; let value = this._map[key1];
var xref = this.xref, suppressEncryption = this.suppressEncryption; if (value === undefined && !(key1 in this._map) && key2 !== undefined) {
if (typeof (value = this._map[key1]) !== 'undefined' || value = this._map[key2];
key1 in this._map || typeof key2 === 'undefined') { if (value === undefined && !(key2 in this._map) && key3 !== undefined) {
if (xref) { value = this._map[key3];
return xref.fetchIfRefAsync(value, suppressEncryption);
} }
return Promise.resolve(value);
} }
if (typeof (value = this._map[key2]) !== 'undefined' || if (value instanceof Ref && this.xref) {
key2 in this._map || typeof key3 === 'undefined') { return this.xref.fetchAsync(value, this.suppressEncryption);
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
} }
value = this._map[key3]; return value;
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
}, },
// Same as get(), but dereferences all elements if the result is an Array. // Same as get(), but dereferences all elements if the result is an Array.
getArray: function Dict_getArray(key1, key2, key3) { getArray(key1, key2, key3) {
var value = this.get(key1, key2, key3); let value = this.get(key1, key2, key3);
var xref = this.xref, suppressEncryption = this.suppressEncryption; if (!Array.isArray(value) || !this.xref) {
if (!Array.isArray(value) || !xref) {
return value; return value;
} }
value = value.slice(); // Ensure that we don't modify the Dict data. value = value.slice(); // Ensure that we don't modify the Dict data.
for (var i = 0, ii = value.length; i < ii; i++) { for (let i = 0, ii = value.length; i < ii; i++) {
if (!isRef(value[i])) { if (!(value[i] instanceof Ref)) {
continue; continue;
} }
value[i] = xref.fetch(value[i], suppressEncryption); value[i] = this.xref.fetch(value[i], this.suppressEncryption);
} }
return value; return value;
}, },