Skip to content

Commit

Permalink
perf(system): uses fast propagation by default
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Oct 12, 2024
1 parent 3867f41 commit 2577eae
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 10 deletions.
6 changes: 6 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Dependency } from './lib/system';

export * from './lib/computed';
export * from './lib/effect';
export * from './lib/effectScope';
export * from './lib/signal';
export * from './lib/system';

export function enableEffectsPropagation() {
Dependency.propagate = Dependency.effectsPropagate;
}
74 changes: 65 additions & 9 deletions lib/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface Link {
prevSubOrUpdate: Link | undefined;
nextSub: Link | undefined;
nextDep: Link | undefined;
prevPropagateOrNextReleased: Link | undefined;
queuedPropagateOrNextReleased: Link | undefined;
}

export const enum DirtyLevels {
Expand Down Expand Up @@ -77,8 +77,8 @@ export namespace Link {
export function get(dep: Dependency, sub: Subscriber): Link {
if (pool !== undefined) {
const link = pool;
pool = link.prevPropagateOrNextReleased;
link.prevPropagateOrNextReleased = undefined;
pool = link.queuedPropagateOrNextReleased;
link.queuedPropagateOrNextReleased = undefined;
link.dep = dep;
link.sub = sub;
return link;
Expand All @@ -89,7 +89,7 @@ export namespace Link {
prevSubOrUpdate: undefined,
nextSub: undefined,
nextDep: undefined,
prevPropagateOrNextReleased: undefined,
queuedPropagateOrNextReleased: undefined,
};
}
}
Expand Down Expand Up @@ -132,7 +132,7 @@ export namespace Link {
link.nextSub = undefined;
link.nextDep = undefined;

link.prevPropagateOrNextReleased = pool;
link.queuedPropagateOrNextReleased = pool;
pool = link;

if (dep.subs === undefined && 'notifyLostSubs' in dep) {
Expand All @@ -145,6 +145,8 @@ export namespace Dependency {

const system = System;

export let propagate = fastPropagate;

// TODO: remove duplication
export function linkSubOnly(dep: Dependency) {
if (system.activeSubIsScopeOrNothing) {
Expand Down Expand Up @@ -228,7 +230,7 @@ export namespace Dependency {
}
}

export function propagate(dep: Dependency) {
export function effectsPropagate(dep: Dependency) {
let depIsEffect = false;
let link = dep.subs;
let dirtyLevel = DirtyLevels.Dirty;
Expand All @@ -248,7 +250,7 @@ export namespace Dependency {
const subIsEffect = 'notify' in sub;

if ('subs' in sub && sub.subs !== undefined) {
sub.deps!.prevPropagateOrNextReleased = link;
sub.deps!.queuedPropagateOrNextReleased = link;
dep = sub;
depIsEffect = subIsEffect;
link = sub.subs;
Expand Down Expand Up @@ -279,10 +281,10 @@ export namespace Dependency {
const depDeps = (dep as Dependency & Subscriber).deps;
if (depDeps !== undefined) {

const prevLink = depDeps.prevPropagateOrNextReleased;
const prevLink = depDeps.queuedPropagateOrNextReleased;

if (prevLink !== undefined) {
depDeps.prevPropagateOrNextReleased = undefined;
depDeps.queuedPropagateOrNextReleased = undefined;
dep = prevLink.dep;
depIsEffect = 'notify' in dep;
link = prevLink.nextSub;
Expand Down Expand Up @@ -317,6 +319,60 @@ export namespace Dependency {
break;
}
}

export function fastPropagate(dep: Dependency) {
let dirtyLevel = DirtyLevels.Dirty;
let currentSubs = dep.subs;
let lastSubs = currentSubs!;

while (currentSubs !== undefined) {
let subLink = currentSubs;

while (true) {
const sub = subLink.sub;
const subDirtyLevel = sub.versionOrDirtyLevel;

if (subDirtyLevel < dirtyLevel) {
sub.versionOrDirtyLevel = dirtyLevel;
}

if (subDirtyLevel === DirtyLevels.None) {

if ('subs' in sub) {
const subSubs = sub.subs;

if (subSubs !== undefined) {
lastSubs.queuedPropagateOrNextReleased = subSubs;
lastSubs = subSubs;
}
}
if ('notify' in sub) {
const queuedEffectsTail = system.queuedEffectsTail;

if (queuedEffectsTail !== undefined) {
queuedEffectsTail.nextNotify = sub;
system.queuedEffectsTail = sub;
} else {
system.queuedEffectsTail = sub;
system.queuedEffects = sub;
}
}
}

const nextSub = subLink.nextSub;
if (nextSub === undefined) {
break;
}
subLink = nextSub;
}

const nextPropagate = currentSubs.queuedPropagateOrNextReleased;
currentSubs.queuedPropagateOrNextReleased = undefined;
currentSubs = nextPropagate;

dirtyLevel = DirtyLevels.MaybeDirty;
}
}
}

export namespace Subscriber {
Expand Down
4 changes: 3 additions & 1 deletion tests/effect.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { expect, test } from 'vitest';
import { computed, effect, effectScope, signal, Subscriber, System } from '..';
import { computed, effect, effectScope, enableEffectsPropagation, signal, Subscriber, System } from '..';

enableEffectsPropagation();

test('should clear subscriptions when untracked by all subscribers', () => {
const a = signal(1);
Expand Down

0 comments on commit 2577eae

Please sign in to comment.