Skip to content

Commit 80ceb0e

Browse files
committed
perf: optimize performance of the DoubleLinkedList get
1 parent 0fedb8e commit 80ceb0e

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

.changeset/gold-terms-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'rrweb': patch
3+
---
4+
5+
perf: optimize performance of the DoubleLinkedList get

packages/rrweb/src/record/mutation.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ function isNodeInLinkedList(n: Node | NodeInLinkedList): n is NodeInLinkedList {
4848
class DoubleLinkedList {
4949
public length = 0;
5050
public head: DoubleLinkedListNode | null = null;
51+
public tail: DoubleLinkedListNode | null = null;
5152

5253
public get(position: number) {
5354
if (position >= this.length) {
@@ -95,6 +96,9 @@ class DoubleLinkedList {
9596
node.next = this.head;
9697
this.head = node;
9798
}
99+
if (node.next === null) {
100+
this.tail = node;
101+
}
98102
this.length++;
99103
}
100104

@@ -108,11 +112,15 @@ class DoubleLinkedList {
108112
this.head = current.next;
109113
if (this.head) {
110114
this.head.previous = null;
115+
} else {
116+
this.tail = null;
111117
}
112118
} else {
113119
current.previous.next = current.next;
114120
if (current.next) {
115121
current.next.previous = current.previous;
122+
} else {
123+
this.tail = current.previous;
116124
}
117125
}
118126
if (n.__ln) {
@@ -368,8 +376,10 @@ export default class MutationBuffer {
368376
}
369377
}
370378
if (!node) {
371-
for (let index = addList.length - 1; index >= 0; index--) {
372-
const _node = addList.get(index);
379+
let tailNode = addList.tail;
380+
while (tailNode) {
381+
const _node = tailNode;
382+
tailNode = tailNode.previous;
373383
// ensure _node is defined before attempting to find value
374384
if (_node) {
375385
const parentId = this.mirror.getId(_node.value.parentNode);
@@ -418,6 +428,7 @@ export default class MutationBuffer {
418428
pushAdd(node.value);
419429
}
420430

431+
addedNodeIndexArr = null;
421432
const payload = {
422433
texts: this.texts
423434
.map((text) => ({

packages/rrweb/test/benchmark/dom-mutation.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ const suites: Array<
3636
eval: 'window.workload()',
3737
times: 5,
3838
},
39+
{
40+
title: 'create 10000 DOM nodes and move it to new container',
41+
html: 'benchmark-dom-mutation-add-and-move.html',
42+
eval: 'window.workload()',
43+
times: 5,
44+
},
3945
];
4046

4147
function avg(v: number[]): number {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<html>
2+
<body>
3+
<div id="app"></div>
4+
</body>
5+
<script>
6+
function appendNodes(parentNode, total) {
7+
const el = document.createElement('div');
8+
for (let i = 0; i < total; i++) {
9+
const div = document.createElement('div');
10+
div.innerHTML = `div-${i + 1}`;
11+
el.append(div);
12+
}
13+
parentNode.append(el);
14+
return el;
15+
}
16+
17+
function addAndMove() {
18+
const app = document.getElementById('app');
19+
20+
const elContainer = appendNodes(app, 10000);
21+
22+
const newAppContainer = document.createElement('div');
23+
24+
newAppContainer.append(elContainer);
25+
26+
document.body.append(newAppContainer);
27+
28+
app.remove();
29+
30+
// necessary
31+
appendNodes(document.body, 1);
32+
}
33+
window.workload = () => {
34+
addAndMove();
35+
};
36+
</script>
37+
</html>

0 commit comments

Comments
 (0)