diff --git a/.changeset/gold-terms-look.md b/.changeset/gold-terms-look.md new file mode 100644 index 0000000000..4ad333341c --- /dev/null +++ b/.changeset/gold-terms-look.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +perf: optimize performance of the DoubleLinkedList get diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index e0b03eb1dd..337394acf1 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -48,6 +48,7 @@ function isNodeInLinkedList(n: Node | NodeInLinkedList): n is NodeInLinkedList { class DoubleLinkedList { public length = 0; public head: DoubleLinkedListNode | null = null; + public tail: DoubleLinkedListNode | null = null; public get(position: number) { if (position >= this.length) { @@ -95,6 +96,9 @@ class DoubleLinkedList { node.next = this.head; this.head = node; } + if (node.next === null) { + this.tail = node; + } this.length++; } @@ -108,11 +112,15 @@ class DoubleLinkedList { this.head = current.next; if (this.head) { this.head.previous = null; + } else { + this.tail = null; } } else { current.previous.next = current.next; if (current.next) { current.next.previous = current.previous; + } else { + this.tail = current.previous; } } if (n.__ln) { @@ -368,8 +376,10 @@ export default class MutationBuffer { } } if (!node) { - for (let index = addList.length - 1; index >= 0; index--) { - const _node = addList.get(index); + let tailNode = addList.tail; + while (tailNode) { + const _node = tailNode; + tailNode = tailNode.previous; // ensure _node is defined before attempting to find value if (_node) { const parentId = this.mirror.getId(_node.value.parentNode); diff --git a/packages/rrweb/test/benchmark/dom-mutation.test.ts b/packages/rrweb/test/benchmark/dom-mutation.test.ts index 57050fb400..3da794db45 100644 --- a/packages/rrweb/test/benchmark/dom-mutation.test.ts +++ b/packages/rrweb/test/benchmark/dom-mutation.test.ts @@ -36,6 +36,12 @@ const suites: Array< eval: 'window.workload()', times: 5, }, + { + title: 'create 10000 DOM nodes and move it to new container', + html: 'benchmark-dom-mutation-add-and-move.html', + eval: 'window.workload()', + times: 5, + }, ]; function avg(v: number[]): number { diff --git a/packages/rrweb/test/html/benchmark-dom-mutation-add-and-move.html b/packages/rrweb/test/html/benchmark-dom-mutation-add-and-move.html new file mode 100644 index 0000000000..922b8c9ffc --- /dev/null +++ b/packages/rrweb/test/html/benchmark-dom-mutation-add-and-move.html @@ -0,0 +1,37 @@ + +
+ + + +