Skip to content

Commit a1291aa

Browse files
committed
perf: guard scheduler queue sorts by level order
1 parent fce4f66 commit a1291aa

1 file changed

Lines changed: 54 additions & 2 deletions

File tree

packages/rescript-signals/src/signals/Scheduler.res

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,58 @@ let compareSubsByLevel = (a: Core.subs, b: Core.subs): float => {
225225
Int.toFloat(a.level - b.level)
226226
}
227227

228+
let needsEffectSort = (effects: array<Core.observer>, ~length: int): bool => {
229+
let i = ref(1)
230+
let previousLevel = ref(0)
231+
let unsorted = ref(false)
232+
233+
switch effects->Array.get(0) {
234+
| Some(effect) => previousLevel := effect.level
235+
| None => ()
236+
}
237+
238+
while i.contents < length && !unsorted.contents {
239+
switch effects->Array.get(i.contents) {
240+
| Some(effect) =>
241+
if previousLevel.contents > effect.level {
242+
unsorted := true
243+
} else {
244+
previousLevel := effect.level
245+
}
246+
| None => ()
247+
}
248+
i := i.contents + 1
249+
}
250+
251+
unsorted.contents
252+
}
253+
254+
let needsSubsSort = (subsList: array<Core.subs>, ~length: int): bool => {
255+
let i = ref(1)
256+
let previousLevel = ref(0)
257+
let unsorted = ref(false)
258+
259+
switch subsList->Array.get(0) {
260+
| Some(subs) => previousLevel := subs.level
261+
| None => ()
262+
}
263+
264+
while i.contents < length && !unsorted.contents {
265+
switch subsList->Array.get(i.contents) {
266+
| Some(subs) =>
267+
if previousLevel.contents > subs.level {
268+
unsorted := true
269+
} else {
270+
previousLevel := subs.level
271+
}
272+
| None => ()
273+
}
274+
i := i.contents + 1
275+
}
276+
277+
unsorted.contents
278+
}
279+
228280
// Compute level for a computed (based on its dependencies)
229281
let computeSubsLevel = (s: Core.subs): int => {
230282
let maxLevel = ref(0)
@@ -418,7 +470,7 @@ let flush = (): unit => {
418470
// Process computeds first (they might trigger more effects)
419471
if pendingComputedSubs->Array.length > 0 {
420472
let computedsLength = pendingComputedSubs->Array.length
421-
if computedsLength > 1 {
473+
if computedsLength > 1 && needsSubsSort(pendingComputedSubs, ~length=computedsLength) {
422474
// Sort by level
423475
pendingComputedSubs->Array.sort(compareSubsByLevel)->ignore
424476
}
@@ -436,7 +488,7 @@ let flush = (): unit => {
436488
// Then process effects
437489
if pendingEffects->Array.length > 0 {
438490
let effectsLength = pendingEffects->Array.length
439-
if effectsLength > 1 {
491+
if effectsLength > 1 && needsEffectSort(pendingEffects, ~length=effectsLength) {
440492
pendingEffects->Array.sort(compareEffectsByLevel)->ignore
441493
}
442494
let i = ref(0)

0 commit comments

Comments
 (0)