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.

Not run yet. The table below fills in as each engine finishes.
JobAegisAlpineVue
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, gzip21 KB islands + templates (91 KB full file)15 KB34 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

Aegis
Alpine
Vue

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.