Cache processed 'ExtGState's in PartialEvaluator.hasBlendModes to avoid unnecessary parsing/lookups

This simply extends the already existing caching of processed resources to avoid duplicated parsing of 'ExtGState's, which should help with badly generated PDF documents.

This patch was tested using the PDF file from issue 6961, i.e. https://github.com/mozilla/pdf.js/files/121712/test.pdf, with the following manifest file:
```
[
    {  "id": "issue6961",
       "file": "../web/pdfs/issue6961.pdf",
       "md5": "",
       "rounds": 200,
       "type": "eq"
    }
]
```

which gave the following *overall* 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      |   400 |         1063 |        1051 | -12 | -1.17 |        faster
Firefox | Page Request |   400 |          552 |         543 |  -9 | -1.69 |        faster
Firefox | Rendering    |   400 |          511 |         508 |  -3 | -0.61 |
```

and the following *page-specific* results:
```
-- Grouped By page, stat --
page | stat         | Count | Baseline(ms) | Current(ms) | +/- |    %  | Result(P<.05)
---- | ------------ | ----- | ------------ | ----------- | --- | ----- | -------------
0    | Overall      |   200 |         1122 |        1110 | -12 | -1.03 |
0    | Page Request |   200 |          552 |         544 |  -8 | -1.48 |        faster
0    | Rendering    |   200 |          570 |         566 |  -4 | -0.62 |
1    | Overall      |   200 |         1005 |         992 | -13 | -1.33 |        faster
1    | Page Request |   200 |          552 |         542 | -11 | -1.91 |        faster
1    | Rendering    |   200 |          452 |         450 |  -3 | -0.61 |
```
This commit is contained in:
Jonas Jenwald 2019-10-12 11:44:07 +02:00
parent af71f9b40a
commit bfcbf2d78d

View File

@ -199,7 +199,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
for (let i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
const key = graphicStatesKeys[i];
var graphicState = graphicStates.get(key);
let graphicState = graphicStates.getRaw(key);
if (graphicState instanceof Ref) {
if (processed[graphicState.toString()]) {
continue; // The ExtGState has already been processed.
}
graphicState = xref.fetch(graphicState);
}
if (!(graphicState instanceof Dict)) {
continue;
}
if (graphicState.objId) {
processed[graphicState.objId] = true;
}
var bm = graphicState.get('BM');
if ((bm instanceof Name) && bm.name !== 'Normal') {
return true;