The same three jobs, three engines
A 10 000-row table, a search filter and an optimistic PATCH, implemented in Aegis 0.7.0, Alpine 3.14 and Vue 3.5. Nothing is precomputed: press Run and the numbers come from your browser, on your machine, medians of three rounds. Alpine and Vue load from cdnjs in their production builds.
| Job | Aegis | Alpine | Vue |
|---|---|---|---|
| Create N rows | – | – | – |
| Filter by “ea” (about a third of the rows) | – | – | – |
| Clear the filter | – | – | – |
| Optimistic PATCH of one row (UI updated before the request) | – | – | – |
| Remove all rows | – | – | – |
| Lines of code for the component | – | – | – |
| Library on the wire, gzip | 21 KB islands + templates (91 KB full file) | 15 KB | 34 KB |
Milliseconds from the state change to the DOM being updated, layout forced. Each engine gets the same data, the same table markup and its own idiomatic code: signals and a keyed list(), x-data with x-for, reactive data with v-for :key. The PATCH job measures only the client side: the row changes first, a mock request follows. Numbers under a millisecond are noise; what to look at is the shape, and whether a job scales with the number of rows or with the number of changed rows.
The stages
The three implementations
Exactly the code that ran, taken from the page's own script. Each exposes create, filter, patch and tick (how the engine flushes) to the harness.
Aegis
Alpine
Vue
Not on this page: React. A React table needs a bundler and either a store or re-renders per change, which makes the comparison about setup rather than the engine; the playground shows the same todo list in React, Vue and Aegis side by side instead. The engine's own numbers on a 1 000-row table are in bench.html and in the benchmarks page.