Skip to content

Commit 1075f94

Browse files
committed
Speed up the PDF render by ~2.5s.
1 parent 3da85e8 commit 1075f94

2 files changed

Lines changed: 386 additions & 0 deletions

File tree

docs/lib/paged.browser.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@
312312
let added = [];
313313

314314
let fragment = document.createDocumentFragment();
315+
// [PATCH: findRef fast-path] Carry an indexOfRefs alongside the
316+
// fragment so callers' findElement(*, fragment) lookups hit the
317+
// fast path, and so the caller can merge this into dest.indexOfRefs
318+
// in one pass after dest.appendChild(fragment). Without this, every
319+
// findElement(rebuiltAncestor, dest) on a subsequent append() call
320+
// falls through to dest.querySelector("[data-ref='...']") — measured
321+
// as 15,767 dictMiss calls ≈ 2.5 s of render on the 1651-page book.
322+
fragment.indexOfRefs = {};
315323

316324
// Handle rowspan on table
317325
if (node.nodeName === "TR") {
@@ -385,6 +393,14 @@
385393
}
386394
added.push(parent);
387395

396+
// [PATCH: findRef fast-path] Record the rebuilt clone in the
397+
// fragment's indexOfRefs so findElement(*, fragment) hits the
398+
// fast path and so dest.indexOfRefs can be updated cheaply by
399+
// the caller (see Layout.append's rebuild branch).
400+
if (parent.dataset && parent.dataset.ref) {
401+
fragment.indexOfRefs[parent.dataset.ref] = parent;
402+
}
403+
388404
// rebuild table rows
389405
if (parent.nodeName === "TD" && ancestor.parentElement.contains(ancestor)) {
390406
let td = ancestor;
@@ -1716,6 +1732,17 @@
17161732
}
17171733

17181734
dest.appendChild(fragment);
1735+
1736+
// [PATCH: findRef fast-path] Merge the rebuilt fragment's
1737+
// indexOfRefs into dest's. Without this, every subsequent
1738+
// findElement(rebuiltAncestor, dest) on this page misses
1739+
// the dict and falls through to dest.querySelector.
1740+
if (fragment.indexOfRefs) {
1741+
if (!dest.indexOfRefs) dest.indexOfRefs = {};
1742+
for (const k in fragment.indexOfRefs) {
1743+
dest.indexOfRefs[k] = fragment.indexOfRefs[k];
1744+
}
1745+
}
17191746
} else {
17201747
dest.appendChild(clone);
17211748
}
@@ -2587,6 +2614,14 @@
25872614
false
25882615
);
25892616

2617+
// [PATCH: findRef fast-path] Populate content.indexOfRefs as we walk
2618+
// so every later findElement(*, source) call hits the dict instead
2619+
// of falling through to source.querySelector("[data-ref='X']"),
2620+
// which scans the entire source DOM (thousands of nodes). Measured
2621+
// as 848 + 42 noDict calls in createBreakToken ≈ 1+ s of render on
2622+
// the 1651-page book.
2623+
if (!content.indexOfRefs) content.indexOfRefs = {};
2624+
25902625
let node = treeWalker.nextNode();
25912626
while(node) {
25922627

@@ -2602,6 +2637,10 @@
26022637
// node.setAttribute("data-children", node.childNodes.length);
26032638

26042639
// node.setAttribute("data-text", node.textContent.trim().length);
2640+
2641+
// [PATCH: findRef fast-path] record after data-ref is guaranteed.
2642+
content.indexOfRefs[node.getAttribute("data-ref")] = node;
2643+
26052644
node = treeWalker.nextNode();
26062645
}
26072646
}

0 commit comments

Comments
 (0)