@zakkster/lite-signal 1.0.3 → 1.0.5
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/README.md +32 -3
- package/llms.txt +2 -2
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
> Zero-GC reactive graph for hot paths. Object-pooled nodes, versioned push-pull propagation, 32-bit modular epochs. Built for 16ms render budgets and 1MB extension bundles.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@zakkster/lite-signal)
|
|
6
|
+

|
|
6
7
|
[](https://bundlephobia.com/package/@zakkster/lite-signal)
|
|
7
8
|
[](https://www.npmjs.com/package/@zakkster/lite-signal)
|
|
8
9
|
[](https://www.npmjs.com/package/@zakkster/lite-signal)
|
|
@@ -365,7 +366,7 @@ These are the questions you'd ask in a code review, with the answers:
|
|
|
365
366
|
|
|
366
367
|
## Benchmarks
|
|
367
368
|
|
|
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 ×
|
|
369
|
+
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 × 50+ outer invocations (median reported). Newer/faster machines shift all libs up proportionally; the relative ordering between libs is what matters.
|
|
369
370
|
|
|
370
371
|
| Scenario | What it stresses | lite-signal | alien-signals | preact | solid-js |
|
|
371
372
|
| ---------- | -------------------------------- | ----------- | ------------- | ---------- | --------- |
|
|
@@ -382,7 +383,7 @@ On allocation pressure, `lite-signal` is alone in the zero-Δheap band: ~15 KB o
|
|
|
382
383
|
|
|
383
384
|
> 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.
|
|
384
385
|
|
|
385
|
-
The benchmark harness is in [`bench/benchmark.mjs`](./bench/benchmark.mjs). It:
|
|
386
|
+
The benchmark harness is in [`bench/benchmark.mjs`](./bench/benchmark.mjs); a full methodology write-up — including the anti-DCE design, workload diagrams, variance discipline, reproducibility recipe, and a self-validation procedure for the harness itself — lives in [`bench/README.md`](./bench/README.md). It:
|
|
386
387
|
|
|
387
388
|
1. Writes every effect's output to a shared `Float64Array(4096)` exposed on `globalThis` — V8 cannot prove these writes are dead.
|
|
388
389
|
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.
|
|
@@ -447,6 +448,34 @@ npm run verify # test + test:gc + a sanity bench
|
|
|
447
448
|
|
|
448
449
|
---
|
|
449
450
|
|
|
451
|
+
## Performance Trade-offs & Topology Scaling
|
|
452
|
+
|
|
453
|
+
`lite-signal` was built with a strict mandate: **absolute zero garbage collection**. By packing the dependency graph into a flat, pre-allocated memory arena, we eliminate the Scavenger GC pauses that plague 120fps Canvas/WebGL loops.
|
|
454
|
+
|
|
455
|
+
However, flat arrays come with a mathematical trade-off. While memory allocation is $O(1)$, modifying a flat array during dynamic dependency churn requires $O(N)$ linear scans.
|
|
456
|
+
|
|
457
|
+
**Andrii Volynets** (author of the phenomenal [Alien Signals](https://github.com/stackblitz/alien-signals)) generously ran `lite-signal` through his advanced topology matrix. The results clearly highlight where the zero-GC flat-array architecture excels, and where pointer-based graphs (like Alien/Reflex) take the lead:
|
|
458
|
+
|
|
459
|
+
#### 1. Stable Topologies (Fan-in / Fan-out / Broadcast)
|
|
460
|
+
In stable environments (typical of game engines, particle systems, and visualizers), `lite-signal` is blisteringly fast and maintains a near-zero allocation profile, keeping frame times perfectly flat.
|
|
461
|
+
|
|
462
|
+
#### 2. Dynamic Topologies (Web Apps / Layered DAGs)
|
|
463
|
+
In highly chaotic graphs with branch switching, selective reads, and wide dense churn (typical of large DOM-based web frameworks like Vue or React), the $O(N)$ edge traversal cost of flat arrays becomes the dominant bottleneck.
|
|
464
|
+
|
|
465
|
+
*Andrii's benchmark results for dynamic topologies:*
|
|
466
|
+
| Scenario | alien-signals | reflex | lite-signal |
|
|
467
|
+
| :--- | :--- | :--- | :--- |
|
|
468
|
+
| **1000x12 (4 sources, dynamic)** | 184ms | 194ms | 2031ms |
|
|
469
|
+
| **1000x5 (25 sources, wide/dense)** | 304ms | 303ms | 1746ms |
|
|
470
|
+
| **64x6 (selective dynamic DAG)** | 181ms | 196ms | 559ms |
|
|
471
|
+
|
|
472
|
+
**The Takeaway:** "Zero-GC" and "topology scalability" are orthogonal dimensions. If you are building a DOM framework with massive dynamic `v-if` churn, use Alien Signals. If you are building a 120fps Canvas game with a stable scene graph where any GC pause is a dropped frame, use `lite-signal`.
|
|
473
|
+
|
|
474
|
+
### Roadmap: v1.1
|
|
475
|
+
We are actively working on a v1.1 architectural update to address this topology degradation while maintaining the zero-GC contract. By moving to a version-stamped dependency reconciliation pass (`lastSeenInEval`) with a pre-allocated scratch buffer, we expect to drop dynamic read costs to $O(1)$ unconditionally.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
450
479
|
## What this is not
|
|
451
480
|
|
|
452
481
|
- **A virtual DOM, JSX runtime, or rendering library.** It's the substrate. Plug it under whatever rendering layer you like.
|
|
@@ -584,4 +613,4 @@ MIT © Zahary Shinikchiev
|
|
|
584
613
|
|
|
585
614
|
---
|
|
586
615
|
|
|
587
|
-
> Part of the **@zakkster** zero-GC stack: [`lite-ecs`](https://www.npmjs.com/package/@zakkster/lite-ecs) · [`lite-ease`](https://www.npmjs.com/package/@zakkster/lite-ease) · [`lite-pointer-tracker`](https://www.npmjs.com/package/@zakkster/lite-pointer-tracker) · [`lite-bmfont`](https://www.npmjs.com/package/@zakkster/lite-bmfont) · [`lite-color`](https://www.npmjs.com/package/@zakkster/lite-color)
|
|
616
|
+
> Part of the **@zakkster** zero-GC stack: [`lite-ecs`](https://www.npmjs.com/package/@zakkster/lite-ecs) · [`lite-ease`](https://www.npmjs.com/package/@zakkster/lite-ease) · [`lite-pointer-tracker`](https://www.npmjs.com/package/@zakkster/lite-pointer-tracker) · [`lite-bmfont`](https://www.npmjs.com/package/@zakkster/lite-bmfont) · [`lite-color`](https://www.npmjs.com/package/@zakkster/lite-color)
|
package/llms.txt
CHANGED
|
@@ -117,7 +117,7 @@ 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 × 50+ invocations)
|
|
121
121
|
|
|
122
122
|
| Scenario | lite-signal | alien-signals | preact | solid |
|
|
123
123
|
| --------------------------------------- | ----------- | ------------- | -------- | -------- |
|
|
@@ -199,4 +199,4 @@ npm install @zakkster/lite-signal
|
|
|
199
199
|
|
|
200
200
|
## License
|
|
201
201
|
|
|
202
|
-
MIT
|
|
202
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zakkster/lite-signal",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
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",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "Signal.js",
|
|
9
|
-
"module": "Signal.js",
|
|
10
|
-
"types": "Signal.d.ts",
|
|
8
|
+
"main": "./Signal.js",
|
|
9
|
+
"module": "./Signal.js",
|
|
10
|
+
"types": "./Signal.d.ts",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"types": "Signal.d.ts",
|
|
14
|
-
"import": "Signal.js",
|
|
15
|
-
"default": "Signal.js"
|
|
13
|
+
"types": "./Signal.d.ts",
|
|
14
|
+
"import": "./Signal.js",
|
|
15
|
+
"default": "./Signal.js"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"files": [
|