Skip to content

Commit 627ed85

Browse files
authored
Perf(renderer): O(1) scope teardown [perf-eval] (#217)
1 parent 149eefc commit 627ed85

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

packages/renderer/src/engines/native/reaction-scope.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export class ReactionScope {
55
this.reactions = [];
66
this.children = [];
77
this.disposers = [];
8+
this.parent = null;
9+
this.index = -1; // this scope's slot in parent.children, for O(1) detach
810
}
911

1012
track(reaction) {
@@ -32,22 +34,31 @@ export class ReactionScope {
3234
child() {
3335
const childScope = new ReactionScope();
3436
childScope.parent = this;
35-
this.children.push(childScope);
37+
childScope.index = this.children.push(childScope) - 1;
3638
return childScope;
3739
}
3840

39-
dispose() {
40-
for (const child of this.children) { child.dispose(); }
41+
// Detach in O(1): a standalone dispose swap-pops itself out of `parent.children`
42+
// via its stored slot index instead of indexOf + splice, and `fromParent` lets a
43+
// parent tearing down its whole subtree skip the per-child unlink (clearing the
44+
// array once). Bulk teardown O(n²) → O(n), and no more splice-mid-iteration.
45+
// (Vue's EffectScope: same fromParent + indexed swap-pop.)
46+
dispose(fromParent = false) {
47+
for (const child of this.children) { child.dispose(true); }
4148
this.children = [];
4249
for (const reaction of this.reactions) { reaction.stop(); }
4350
this.reactions = [];
4451
for (const fn of this.disposers) { fn(); }
4552
this.disposers = [];
46-
// Remove from parent to prevent accumulation across branch switches
47-
if (this.parent) {
48-
const idx = this.parent.children.indexOf(this);
49-
if (idx !== -1) { this.parent.children.splice(idx, 1); }
50-
this.parent = null;
53+
if (!fromParent && this.parent) {
54+
const siblings = this.parent.children;
55+
const last = siblings.pop();
56+
if (last && last !== this && this.index < siblings.length) {
57+
siblings[this.index] = last;
58+
last.index = this.index;
59+
}
5160
}
61+
this.parent = null;
62+
this.index = -1;
5263
}
5364
}

0 commit comments

Comments
 (0)