Skip to content

Commit 16b61f8

Browse files
committed
compare: full 13.8.4 vs Alpine run — 2.27× CPU geomean, 3.27× less memory, first paint 76ms; refresh sizes
1 parent c7ef334 commit 16b61f8

3 files changed

Lines changed: 25 additions & 23 deletions

File tree

compare.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ Sprae, [Alpine](https://alpinejs.dev) and [petite-vue](https://github.com/vuejs/
1111

1212
| | sprae | Alpine | petite-vue |
1313
|---|---|---|---|
14-
| CDN build, min+gzip | **10.7kb** | 16.7kb | 7.1kb |
15-
| CPU speed, [geometric mean](#performance) | **1.73× faster** | baseline | not benchmarked |
16-
| First paint (1k rows) | **83ms** | 165ms | not benchmarked |
14+
| CDN build, min+gzip | **10.9kb** | 16.7kb | 7.1kb |
15+
| CPU speed, [geometric mean](#performance) | **2.27× faster** | baseline | not benchmarked |
16+
| Runtime memory (1k rows) | **5.1MB** | 16.6MB | not benchmarked |
17+
| First paint (1k rows) | **76ms** | 107ms | not benchmarked |
1718
| Strict CSP / no-eval | [full JS expressions](./csp) | [restricted subset](https://alpinejs.dev/advanced/csp) | none |
1819
| Reactivity | pluggable signals ([TC39-track](https://github.com/tc39/proposal-signals)) | bundled @vue/reactivity | bundled @vue/reactivity |
1920
| Keyed lists | automatic (by identity) | manual `:key` | manual `:key` |
@@ -22,26 +23,27 @@ Sprae, [Alpine](https://alpinejs.dev) and [petite-vue](https://github.com/vuejs/
2223
| Status | active, 0 open issues | active | frozen — last release Jan 2022 |
2324
| License | MIT | MIT | MIT |
2425

25-
<small>Sizes current as of 2026-07-03 (sprae 13.7.1, Alpine 3.15.12, petite-vue 0.4.1); CPU speed and first paint are from the last full benchmark run at sprae 13.3.8 — see [Methodology](#methodology).</small>
26+
<small>Sizes current as of 2026-07-28 (sprae 13.8.4, Alpine 3.15.12, petite-vue 0.4.1); CPU speed, memory and first paint are from a full benchmark run at sprae 13.8.4 — see [Methodology](#methodology).</small>
2627

2728
## Performance
2829

29-
Median times in ms (lower is better), [js-framework-benchmark](https://krausest.github.io/js-framework-benchmark/) keyed suite, last full run at sprae v13.3.8 vs Alpine v3.14.7, identical machine and Chrome:
30+
Median times in ms (lower is better), [js-framework-benchmark](https://krausest.github.io/js-framework-benchmark/) keyed suite, full run 2026-07-28 at sprae v13.8.4 vs Alpine v3.14.7, identical machine and Chrome 147:
3031

3132
| benchmark | sprae | Alpine | ratio |
3233
|---|---|---|---|
33-
| create 1,000 rows | 54.6 | 88.2 | 1.62× |
34-
| replace all rows | 56.4 | 109.5 | 1.94× |
35-
| partial update (every 10th) | 21.4 | 27.8 | 1.30× |
36-
| select row | 13.8 | 50.7 | 3.67× |
37-
| swap rows | 35.5 | 35.2 | 0.99× |
38-
| remove row | 19.3 | 26.2 | 1.36× |
39-
| create 10,000 rows | 515.9 | 883.7 | 1.71× |
40-
| append 1,000 rows | 59.0 | 97.9 | 1.66× |
41-
| clear rows | 32.8 | 80.9 | 2.47× |
42-
| **geometric mean** | | | **1.73×** |
43-
| first paint | 82.6 | 164.7 | 1.99× |
44-
| transferred size (benchmark app) | 7.9kb | 14.7kb | 1.86× |
34+
| create 1,000 rows | 29.7 | 67.7 | 2.28× |
35+
| replace all rows | 32.2 | 83.4 | 2.59× |
36+
| partial update (every 10th) | 19.8 | 22.4 | 1.13× |
37+
| select row | 7.4 | 41.4 | 5.59× |
38+
| swap rows | 20.8 | 38.1 | 1.83× |
39+
| remove row | 19.0 | 22.0 | 1.16× |
40+
| create 10,000 rows | 339.8 | 737.5 | 2.17× |
41+
| append 1,000 rows | 35.1 | 78.5 | 2.24× |
42+
| clear rows | 15.6 | 64.4 | 4.13× |
43+
| **geometric mean** | | | **2.27×** |
44+
| memory after create 1,000 rows | 5.1MB | 16.6MB | 3.27× |
45+
| first paint | 75.5 | 106.5 | 1.41× |
46+
| transferred size (benchmark app) | 10.0kb | 14.7kb | 1.47× |
4547

4648
Run it independently: [krausest/js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) includes both frameworks.
4749

@@ -64,14 +66,14 @@ Honesty over conversion:
6466

6567
## Methodology
6668

67-
Sizes measured 2026-07-03, unpkg default build of each package (sprae 13.7.1, Alpine 3.15.12, petite-vue 0.4.1):
69+
Sizes measured 2026-07-28, unpkg default build of each package (sprae 13.8.4, Alpine 3.15.12, petite-vue 0.4.1):
6870

6971
```sh
70-
curl -sL https://unpkg.com/sprae | gzip -9 | wc -c # 10708
72+
curl -sL https://unpkg.com/sprae | gzip -9 | wc -c # 10947
7173
curl -sL https://unpkg.com/alpinejs | gzip -9 | wc -c # 16694
7274
curl -sL https://unpkg.com/petite-vue | gzip -9 | wc -c # 7061
7375
```
7476

75-
sprae's ESM build (`sprae.js`) is smaller — 9.7kb gzip, 8.9kb brotli — if you import it directly.
77+
sprae's ESM build (`sprae.js`) is smaller — 9.9kb gzip, 9.1kb brotli — if you import it directly.
7678

77-
Performance: [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) official methodology, both frameworks run on the same machine, same Chrome, 15 samples per benchmark, medians reported — last full run at sprae v13.3.8 vs Alpine v3.14.7. Transferred size row is measured by the benchmark harness itself.
79+
Performance: [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) official webdriver-ts harness, both frameworks on the same machine, Chrome 147, 15 samples per benchmark, medians reported — full run 2026-07-28 at sprae v13.8.4 vs Alpine v3.14.7 (the Alpine version pinned by the benchmark's own implementation). Memory is the harness's GC'd heap after create-1k; transferred size and first paint are measured by the harness itself.

index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ document.querySelectorAll('.ref-list pre').forEach(p => p.innerHTML = hl(p.textC
301301
## FAQ
302302

303303
**How does it compare?**
304-
: ~1.6× lighter and ~1.7× faster than Alpine — [measured](./compare). Actively maintained, unlike petite-vue. [Signals](https://github.com/tc39/proposal-signals)-powered (emerging standard). Migrating? [Alpine → sprae guide](./alpine).
304+
: ~1.5× smaller wire, ~2.3× faster, ~3× less runtime memory than Alpine — [measured](./compare). Actively maintained, unlike petite-vue. [Signals](https://github.com/tc39/proposal-signals)-powered (emerging standard). Migrating? [Alpine → sprae guide](./alpine).
305305

306306
**Strict CSP? Browser extension?**
307307
: Yes — the [CSP build](./csp) runs full JS expressions with no `eval` / `new Function`, where Alpine's CSP build forbids even arrow functions. Works in Chrome MV3 extensions.

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ Works with [define-element](https://github.com/dy/define-element), Lit, or any C
519519
If you know HTML and JS, you know sprae. Just `:attribute="expression"`.
520520

521521
**How does it compare to Alpine?**<br>
522-
~1.6× lighter and ~1.7× faster — [measured](https://dy.github.io/sprae/compare). Pluggable signals, built-in modifiers, event chains, full-JS [CSP build](https://dy.github.io/sprae/csp).
522+
~1.5× smaller wire, ~2.3× faster, ~3× less runtime memory[measured](https://dy.github.io/sprae/compare). Pluggable signals, built-in modifiers, event chains, full-JS [CSP build](https://dy.github.io/sprae/csp).
523523

524524
**How does it compare to React/Vue?**<br>
525525
No build step, no virtual DOM. Can inject into [JSX](#jsx--nextjs) for server components without framework overhead.

0 commit comments

Comments
 (0)