@@ -242,11 +242,21 @@ class Computation<T> implements SourceType, ObserverType, Owner {
242242 }
243243
244244 read ( ) : T {
245- // OPTIMIZATION: Fast path for CLEAN state
245+ // OPTIMIZATION: Extract state once, fast path for CLEAN
246246 const state = this . _state & 3 ;
247247
248248 if ( currentObserver ) {
249- track ( this ) ;
249+ // OPTIMIZATION: Inline track - avoid function call
250+ const sources = currentObserver . _sources ;
251+ if ( ! newSources && sources && sources [ newSourcesIndex ] === this ) {
252+ newSourcesIndex ++ ;
253+ } else if ( ! newSources ) {
254+ newSources = [ this ] ;
255+ } else if ( this !== newSources [ newSources . length - 1 ] ) {
256+ newSources . push ( this ) ;
257+ }
258+
259+ // Only check if not CLEAN
250260 if ( state !== STATE_CLEAN ) {
251261 this . _updateIfNecessary ( ) ;
252262 }
@@ -284,33 +294,37 @@ class Computation<T> implements SourceType, ObserverType, Owner {
284294 _updateIfNecessary ( ) : void {
285295 const state = this . _state & 3 ;
286296
287- if ( state === STATE_DISPOSED || state === STATE_CLEAN ) {
288- return ;
289- }
297+ // OPTIMIZATION: Fast exit for CLEAN or DISPOSED
298+ if ( state === STATE_CLEAN || state === STATE_DISPOSED ) return ;
290299
291300 if ( state === STATE_CHECK ) {
292- // SOLID.JS PATTERN: Check ALL sources recursively first
293301 const sources = this . _sources ;
294302 if ( sources ) {
303+ const myTime = this . _time ;
295304 const len = sources . length ;
305+
306+ // OPTIMIZATION: Check all sources, early exit if any changed
296307 for ( let i = 0 ; i < len ; i ++ ) {
297308 sources [ i ] . _updateIfNecessary ( ) ;
298309
299- // OPTIMIZATION: Early exit if changed (avoid checking remaining sources)
300- if ( sources [ i ] . _time > this . _time ) {
310+ // Early exit optimization
311+ if ( sources [ i ] . _time > myTime ) {
301312 this . _state = ( this . _state & ~ 3 ) | STATE_DIRTY ;
302313 break ;
303314 }
304315 }
305316 }
317+
318+ // After checking, if still CHECK, mark CLEAN
319+ if ( ( this . _state & 3 ) === STATE_CHECK ) {
320+ this . _state = ( this . _state & ~ 3 ) | STATE_CLEAN ;
321+ return ;
322+ }
306323 }
307324
308- // Only update if still dirty after checking sources
325+ // Only update if DIRTY
309326 if ( ( this . _state & 3 ) === STATE_DIRTY ) {
310327 this . update ( ) ;
311- } else if ( ( this . _state & 3 ) === STATE_CHECK ) {
312- // OPTIMIZATION: Set CLEAN if still CHECK after verifying all sources
313- this . _state = ( this . _state & ~ 3 ) | STATE_CLEAN ;
314328 }
315329 }
316330
@@ -405,25 +419,27 @@ class Computation<T> implements SourceType, ObserverType, Owner {
405419
406420 _notify ( state : number ) : void {
407421 const currentState = this . _state & 3 ;
408- const isExecutingSelf = currentObserver === this ;
409422
423+ // OPTIMIZATION: Fast path - already at or past this state
410424 if ( currentState >= state || currentState === STATE_DISPOSED ) {
411- if ( isExecutingSelf && ( state === STATE_DIRTY || state === STATE_CHECK ) && this . _effectType !== EFFECT_PURE ) {
412- // Effect is executing and received a notification - ALWAYS schedule for next round
413- // Even if FLAG_PENDING is set (it will be from the current execution)
425+ // Special handling for self-executing effects
426+ if ( currentObserver === this && state >= STATE_CHECK && this . _effectType !== EFFECT_PURE ) {
414427 this . _state |= FLAG_PENDING ;
415428 pendingEffects [ pendingCount ++ ] = this ;
416429 }
417430 return ;
418431 }
419432
433+ // Update state
420434 this . _state = ( this . _state & ~ 3 ) | state ;
421435
436+ // Schedule user effects
422437 if ( this . _effectType !== EFFECT_PURE ) {
423438 scheduleEffect ( this ) ;
424439 }
425440
426- if ( state === STATE_DIRTY || state === STATE_CHECK ) {
441+ // Propagate CHECK to observers
442+ if ( state >= STATE_CHECK ) {
427443 this . _notifyObservers ( STATE_CHECK ) ;
428444 }
429445 }
@@ -432,8 +448,15 @@ class Computation<T> implements SourceType, ObserverType, Owner {
432448 const observers = this . _observers ;
433449 if ( ! observers ) return ;
434450
435- // OPTIMIZATION: Batch notify to reduce intermediate work
436451 const len = observers . length ;
452+
453+ // OPTIMIZATION: Single observer fast path
454+ if ( len === 1 ) {
455+ observers [ 0 ] . _notify ( state ) ;
456+ return ;
457+ }
458+
459+ // OPTIMIZATION: Batch for large observer counts
437460 if ( len > 100 ) {
438461 batchDepth ++ ;
439462 for ( let i = 0 ; i < len ; i ++ ) {
@@ -484,14 +507,11 @@ class Signal<T> implements SourceType {
484507 }
485508
486509 get value ( ) : T {
487- // OPTIMIZATION: Inline track check
510+ // OPTIMIZATION: Inline track - avoid function call overhead
488511 if ( currentObserver ) {
489- // OPTIMIZATION: Compare with old sources first
490- if (
491- ! newSources &&
492- currentObserver . _sources &&
493- currentObserver . _sources [ newSourcesIndex ] === this
494- ) {
512+ const sources = currentObserver . _sources ;
513+ // OPTIMIZATION: Fast path - source unchanged at same index
514+ if ( ! newSources && sources && sources [ newSourcesIndex ] === this ) {
495515 newSourcesIndex ++ ;
496516 } else if ( ! newSources ) {
497517 newSources = [ this ] ;
@@ -508,29 +528,32 @@ class Signal<T> implements SourceType {
508528 this . _value = next ;
509529 this . _time = ++ clock ;
510530
511- if ( ! this . _observers ) return ;
531+ const observers = this . _observers ;
532+ if ( ! observers ) return ;
533+
534+ const len = observers . length ;
512535
513- // OPTIMIZATION: Skip batching overhead for small observer counts
514- const len = this . _observers . length ;
536+ // OPTIMIZATION: Fast path for single observer (common case)
515537 if ( len === 1 ) {
516- // Fast path for single observer
517- this . _observers [ 0 ] . _notify ( STATE_DIRTY ) ;
518- if ( batchDepth === 0 && ! isFlushScheduled && pendingCount > 0 ) {
538+ observers [ 0 ] . _notify ( STATE_DIRTY ) ;
539+ // Only flush if effects are pending and not already scheduled
540+ if ( batchDepth === 0 && pendingCount > 0 && ! isFlushScheduled ) {
519541 isFlushScheduled = true ;
520542 flushEffects ( ) ;
521543 }
522- } else {
523- // Auto-batching for multiple observers
524- batchDepth ++ ;
525- for ( let i = 0 ; i < len ; i ++ ) {
526- this . _observers [ i ] . _notify ( STATE_DIRTY ) ;
527- }
528- batchDepth -- ;
544+ return ;
545+ }
529546
530- if ( batchDepth === 0 && ! isFlushScheduled && pendingCount > 0 ) {
531- isFlushScheduled = true ;
532- flushEffects ( ) ;
533- }
547+ // Auto-batching for multiple observers
548+ batchDepth ++ ;
549+ for ( let i = 0 ; i < len ; i ++ ) {
550+ observers [ i ] . _notify ( STATE_DIRTY ) ;
551+ }
552+ batchDepth -- ;
553+
554+ if ( batchDepth === 0 && pendingCount > 0 && ! isFlushScheduled ) {
555+ isFlushScheduled = true ;
556+ flushEffects ( ) ;
534557 }
535558 }
536559
0 commit comments