diff --git a/.changeset/kind-kids-design.md b/.changeset/kind-kids-design.md new file mode 100644 index 0000000000..764d3fde1c --- /dev/null +++ b/.changeset/kind-kids-design.md @@ -0,0 +1,5 @@ +--- +"rrweb": patch +--- + +Optimize performance of isParentRemoved by converting it to an iterative procedure diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index f4267af340..d96fab315d 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -802,15 +802,15 @@ function _isParentRemoved( n: Node, mirror: Mirror, ): boolean { - const { parentNode } = n; - if (!parentNode) { - return false; - } - const parentId = mirror.getId(parentNode); - if (removes.some((r) => r.id === parentId)) { - return true; + let node: ParentNode | null = n.parentNode; + while (node) { + const parentId = mirror.getId(node); + if (removes.some((r) => r.id === parentId)) { + return true; + } + node = node.parentNode; } - return _isParentRemoved(removes, parentNode, mirror); + return false; } function isAncestorInSet(set: Set, n: Node): boolean { diff --git a/packages/rrweb/test/benchmark/dom-mutation.test.ts b/packages/rrweb/test/benchmark/dom-mutation.test.ts index a4124c3f98..447024c102 100644 --- a/packages/rrweb/test/benchmark/dom-mutation.test.ts +++ b/packages/rrweb/test/benchmark/dom-mutation.test.ts @@ -18,6 +18,12 @@ const suites: Array< // eval: 'document.querySelector("button").click()', // times: 10, // }, + { + title: 'create 1000x 1 DOM nodes with deeply nested children', + html: 'benchmark-dom-mutation-deep-nested.html', + eval: 'window.workload()', + times: 10, + }, { title: 'create 1000x10 DOM nodes', html: 'benchmark-dom-mutation.html', diff --git a/packages/rrweb/test/html/benchmark-dom-mutation-deep-nested.html b/packages/rrweb/test/html/benchmark-dom-mutation-deep-nested.html new file mode 100644 index 0000000000..fd0a4258b2 --- /dev/null +++ b/packages/rrweb/test/html/benchmark-dom-mutation-deep-nested.html @@ -0,0 +1,31 @@ + + + +