From 02e711da8ae41e668191cab9d24dad110fcb54c5 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 19 Apr 2024 13:38:28 -0230 Subject: [PATCH] upstream: perf(rrweb): attribute mutation optimization (#178) Ref: https://github.com/rrweb-io/rrweb/pull/1343 Co-authored-by: Michael Dellanoce --- .changeset/moody-dots-refuse.md | 5 +++++ packages/rrweb/src/record/mutation.ts | 7 ++++--- .../rrweb/test/benchmark/dom-mutation.test.ts | 6 ++++++ .../benchmark-dom-mutation-attributes.html | 21 +++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 .changeset/moody-dots-refuse.md create mode 100644 packages/rrweb/test/html/benchmark-dom-mutation-attributes.html diff --git a/.changeset/moody-dots-refuse.md b/.changeset/moody-dots-refuse.md new file mode 100644 index 0000000000..32270da384 --- /dev/null +++ b/.changeset/moody-dots-refuse.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +use WeakMap for faster attributeCursor lookup while processing attribute mutations diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index 3afc6e598d..f4c23a818c 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -144,6 +144,7 @@ export default class MutationBuffer { private texts: textCursor[] = []; private attributes: attributeCursor[] = []; + private attributeMap = new WeakMap(); private removes: removedNodeMutation[] = []; private mapRemoves: Node[] = []; @@ -502,6 +503,7 @@ export default class MutationBuffer { // reset this.texts = []; this.attributes = []; + this.attributeMap = new WeakMap(); this.removes = []; this.addedSet = new Set(); this.movedSet = new Set(); @@ -602,9 +604,7 @@ export default class MutationBuffer { return; } - let item: attributeCursor | undefined = this.attributes.find( - (a) => a.node === m.target, - ); + let item = this.attributeMap.get(m.target); if ( target.tagName === 'IFRAME' && attributeName === 'src' && @@ -626,6 +626,7 @@ export default class MutationBuffer { _unchangedStyles: {}, }; this.attributes.push(item); + this.attributeMap.set(m.target, item); } // Keep this property on inputs that used to be password inputs diff --git a/packages/rrweb/test/benchmark/dom-mutation.test.ts b/packages/rrweb/test/benchmark/dom-mutation.test.ts index fc41472906..94019c6d4c 100644 --- a/packages/rrweb/test/benchmark/dom-mutation.test.ts +++ b/packages/rrweb/test/benchmark/dom-mutation.test.ts @@ -46,6 +46,12 @@ const suites: Array< eval: 'window.workload()', times: 5, }, + { + title: 'modify attributes on 10000 DOM nodes', + html: 'benchmark-dom-mutation-attributes.html', + eval: 'window.workload()', + times: 10, + }, { title: 'mask 1000x10 DOM nodes', html: 'benchmark-text-masking.html', diff --git a/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html b/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html new file mode 100644 index 0000000000..3d00b26b4d --- /dev/null +++ b/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html @@ -0,0 +1,21 @@ + + + +