@zakkster/lite-signal 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Zahary
3
+ Copyright (c) 2026 Zahary Shinikchiev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@zakkster/lite-signal.svg?style=for-the-badge&color=latest)](https://www.npmjs.com/package/@zakkster/lite-signal)
6
6
  [![bundle size](https://img.shields.io/badge/min%2Bgz-~3.2KB-blue?style=flat-square)](https://bundlephobia.com/package/@zakkster/lite-signal)
7
- [![npm downloads](https://img.shields.io/npm/dm/@zakkster/lite-signale?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-signal)
7
+ [![npm downloads](https://img.shields.io/npm/dm/@zakkster/lite-signal?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-signal)
8
8
  [![npm total downloads](https://img.shields.io/npm/dt/@zakkster/lite-signal?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-signal)
9
9
  ![TypeScript](https://img.shields.io/badge/TypeScript-Types-informational)
10
10
  ![Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)
@@ -365,22 +365,24 @@ These are the questions you'd ask in a code review, with the answers:
365
365
 
366
366
  ## Benchmarks
367
367
 
368
- Honest numbers, against the same workload, with anti-DCE sinks and verified effect execution. All measurements: Node 22, **2016-era Intel MacBook Pro (4 cores, ~10 yr old hardware)**, 20K iterations × 5 runs (median reported). Newer/faster machines shift all libs up proportionally; the relative ordering between libs is what matters.
368
+ Honest numbers, against the same workload, with anti-DCE sinks and verified effect execution. All measurements: Node 22, **2016-era Intel MacBook Pro (4 cores, ~10 yr old hardware)**, 20K iterations × 5 inner runs × 12 outer invocations (median reported). Newer/faster machines shift all libs up proportionally; the relative ordering between libs is what matters.
369
369
 
370
370
  | Scenario | What it stresses | lite-signal | alien-signals | preact | solid-js |
371
371
  | ---------- | -------------------------------- | ----------- | ------------- | ---------- | --------- |
372
- | **MUX** | 256 signals → 1 sum → 1 effect (fan-in) | **252K ops/s** | 191K | 153K | 76K |
373
- | **KAIROS** | 1 signal → 1000 computeds 1 effect | **15K** | 14K | 11K | 4K |
374
- | **BROADCAST** | 1 signal → 1000 effects (fan-out) | 23K | **26K** | 16K | 7K |
375
- | **DEEP CHAIN** | 256-deep computed chain → 1 effect | 52K | **87K** | 49K | 15K |
376
- | **Δheap MUX** | transient alloc pressure | **15 KB** | 13 KB | 230 KB | 2,834 KB |
377
- | **Retained MUX** | state surviving forced GC | **−20 KB** (none) | −2 KB | −13 KB | −14 KB |
372
+ | **MUX** | 256 signals → 1 sum → 1 effect (fan-in) | **249K ops/s** | 207K | 153K | 77K |
373
+ | **BROADCAST** | 1 signal → 1000 effects (fan-out) | **24K** | 22K | 17K | 8K |
374
+ | **KAIROS** | 1 signal → 1000 computeds 1 effect | **14K** | 13K | 12K | 4K |
375
+ | **DEEP CHAIN** | 256-deep computed chain → 1 effect | 51K | **60K** | 50K | 15K |
376
+ | **Δheap MUX** | transient alloc pressure | **15 KB** | 3,920 KB | 4,325 KB | 2,816 KB |
377
+ | **Retained MUX** | state surviving forced GC | **−20 KB** (none) | −2 KB | −6 KB | −3 KB |
378
378
 
379
- **Reading the table:** `lite-signal` wins **MUX** (fan-in aggregation) by **+32%** over alien-signals the dominant pattern in dashboards, scoreboards, HUDs, and leaderboards. It also edges ahead on **KAIROS** (one source fanning into a wide layer of memos) by ~7%, though that gap is within run-to-run noise. On pure fan-out (BROADCAST) and long pipelines (DEEP CHAIN), `alien-signals`' flatter internal representation is faster by 13% and 67% respectively. On allocation pressure, `lite-signal` and `alien-signals` are in a different league: Preact pays ~230 KB of churn per MUX run, Solid pays ~2.8 MB. Negative "retained" numbers mean V8 reclaimed more memory than the bench allocated during the post-run forced GC — no leaks anywhere.
379
+ **Reading the table:** `lite-signal` wins **MUX** (fan-in aggregation) by **+20%**, **BROADCAST** (fan-out) by **+9%**, and **KAIROS** (one source feeding a wide layer of memos) by **+8%** three of the four scenarios. These are the patterns that dominate real UI workloads: dashboards, scoreboards, HUDs, leaderboards, and any view that aggregates many inputs into a single computed slice. `alien-signals` retains a **−15% lead on DEEP CHAIN** (256-deep computed pipelines), where a flatter internal representation pays off when the propagation path is long rather than wide.
380
+
381
+ On allocation pressure, `lite-signal` is alone in the zero-Δheap band: ~15 KB of transient garbage across 20,000 iterations regardless of scenario. preact runs ~230 KB per loop, solid runs into single-digit megabytes, and alien-signals — which earlier shared the zero-GC band with lite-signal — now allocates 0.9-3.9 MB per scenario in current published versions. Negative "retained" numbers mean V8 reclaimed memory below the pre-bench baseline during the post-run forced GC — no leaks anywhere.
380
382
 
381
383
  > Note on the +71 KB retained that lite-signal shows on KAIROS specifically: that's the pre-allocated pool sitting in memory holding the live graph (1002 nodes + ~2000 links). The pool *is* the working memory — see the [Case for object pooling](#case-for-object-pooling) section. On the other benches the graph is small enough that the same pool floats below baseline after GC.
382
384
 
383
- The benchmark harness is in [`bench/bench.mjs`](./bench/bench.mjs). It:
385
+ The benchmark harness is in [`bench/benchmark.mjs`](./bench/benchmark.mjs). It:
384
386
 
385
387
  1. Writes every effect's output to a shared `Float64Array(4096)` exposed on `globalThis` — V8 cannot prove these writes are dead.
386
388
  2. Uses the **client** Solid runtime (`solid-js/dist/solid.js`), not the SSR stub Node resolves to by default. The default Node resolution silently no-ops effects, which is how earlier benchmarks across the ecosystem have reported Solid at ~50 GHz throughput.
@@ -578,7 +580,7 @@ npm run verify # all of the above; gate for publish
578
580
 
579
581
  ## License
580
582
 
581
- MIT © Zahary Karadjov
583
+ MIT © Zahary Shinikchiev
582
584
 
583
585
  ---
584
586
 
package/llms.txt CHANGED
@@ -117,20 +117,28 @@ class CapacityError extends Error {
117
117
  }
118
118
  ```
119
119
 
120
- ## Benchmark snapshot (Node 22, 2016-era Intel MacBook Pro, 20K iter × 5 runs)
120
+ ## Benchmark snapshot (Node 22, 2016-era Intel MacBook Pro, 20K iter × 5 runs × 12 invocations)
121
121
 
122
122
  | Scenario | lite-signal | alien-signals | preact | solid |
123
123
  | --------------------------------------- | ----------- | ------------- | -------- | -------- |
124
- | MUX (256 sigs → sum → effect) | **252K ops/s** | 191K | 153K | 76K |
125
- | KAIROS (1 sig → 1000 computeds → eff) | **15K** | 14K | 11K | 4K |
126
- | BROADCAST (1 sig → 1000 effects) | 23K | **26K** | 16K | 7K |
127
- | DEEP CHAIN (256-deep memos → eff) | 52K | **87K** | 49K | 15K |
128
-
129
- lite-signal wins MUX (+32% vs alien) and is effectively tied with alien on KAIROS
130
- (+7%, within noise). alien wins BROADCAST (+13%) and DEEP CHAIN (+67%); alien's
131
- flatter internal representation has lower per-edge cost on long pipelines and
132
- pure broadcast. Both libs allocate orders of magnitude less than preact/solid
133
- during the timed loop (15-20 KB Δheap vs 230 KB-2.8 MB).
124
+ | MUX (256 sigs → sum → effect) | **249K ops/s** | 207K | 153K | 77K |
125
+ | BROADCAST (1 sig → 1000 effects) | **24K** | 22K | 17K | 8K |
126
+ | KAIROS (1 sig → 1000 computeds → eff) | **14K** | 13K | 12K | 4K |
127
+ | DEEP CHAIN (256-deep memos → eff) | 51K | **60K** | 50K | 15K |
128
+
129
+ lite-signal wins three of four scenarios against current published versions of the
130
+ alternatives: MUX +20%, BROADCAST +9%, KAIROS +8% fan-in aggregation, fan-out
131
+ broadcast, and one-source-to-wide-memo-layer respectively. These are the patterns
132
+ that dominate UI workloads. alien-signals retains a 15% lead on 256-deep computed
133
+ pipelines, where its flatter internal representation pays off when the propagation
134
+ path is long rather than wide.
135
+
136
+ On allocation pressure, lite-signal is alone in the zero-Δheap band: ~15 KB of
137
+ transient garbage per 20,000-iteration loop, regardless of scenario. preact runs
138
+ ~230 KB per loop; solid runs into single-digit megabytes; alien-signals — which
139
+ earlier shared the zero-GC band — now allocates 0.9-3.9 MB per scenario in its
140
+ current published version (not a leak; retained heap is near zero everywhere,
141
+ but it is real GC pressure on the hot path).
134
142
 
135
143
  Retained heap after forced GC: typically negative for all libs (V8 compacts).
136
144
  The one exception: lite-signal shows ~+71 KB retained on KAIROS, which is the
@@ -171,13 +179,15 @@ sandbox.destroy(); // entire reactive world reset
171
179
 
172
180
  ## File layout
173
181
 
174
- - `src/index.js` — full implementation, ~500 lines, single file.
175
- - `types/index.d.ts` — TypeScript declarations for all public API.
182
+ - `Signal.js` — full implementation, ~500 lines, single file.
183
+ - `Signal.d.ts` — TypeScript declarations for all public API.
176
184
  - `test/01-core.test.mjs` — signal/computed/effect basics, equality, untrack.
177
185
  - `test/02-topology.test.mjs` — diamonds, chains, fan-out/in, cycle detection.
178
186
  - `test/03-pool.test.mjs` — capacity errors, grow policy, pool reuse.
179
187
  - `test/04-zero-gc.test.mjs` — heap retention (run with --expose-gc).
180
188
  - `test/05-scheduler.test.mjs` — scheduler races, dispose, gen counter, version wrap.
189
+ - `test/06-nested-objects.test.mjs` — nested-object & reference-identity behaviours.
190
+ - `test/07-dispose.test.mjs` — universal disposal: registry.dispose(api).
181
191
  - `bench/bench.mjs` — comparative benchmark vs alien-signals, preact, solid.
182
192
  - `demo/index.html` — interactive visualization of the reactive graph.
183
193
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zakkster/lite-signal",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Zero-GC reactive graph. Monomorphic object pool, versioned push-pull propagation, 32-bit modular versioning. Built for hot paths and long-running processes.",
5
5
  "author": "Zahary Shinikchiev <shinikchiev@yahoo.com>",
6
6
  "license": "MIT",