Skip to content
Meltea

Benchmarks

Within ×1.2 of hand-written JavaScript.

A local reproduction of the keyed CPU, memory and size tests of js-framework-benchmark, in headless Chrome, for Meltea against hand-written vanilla JS and React 18 with hooks. The ratios move by about 0.1 between runs.

Time, geometric mean of nine keyed operations

Slowdown against hand-written vanilla JS

lower is better
  • vanilla JS×1.00
  • Meltea×1.15
  • React 18×1.70
› Show as a table
frameworkSlowdown against hand-written vanilla JS
vanilla JS×1.00
Meltea×1.15
React 18×1.70

JavaScript of the benchmark app

gzip size of all JS in the production bundle

smaller is better
  • vanilla JS1.4 kB
  • Meltea9.0 kB
  • React 1845.6 kB
› Show as a table
frameworkgzip size of all JS in the production bundle
vanilla JS1.4 kB
Meltea9.0 kB
React 1845.6 kB

Heap with 1,000 rows

After two forced garbage collections

smaller is better
  • vanilla JS0.77 MB
  • Meltea1.22 MB
  • React 183.17 MB
› Show as a table
frameworkAfter two forced garbage collections
vanilla JS0.77 MB
Meltea1.22 MB
React 183.17 MB

Swap two rows of 1,000

Slowdown against hand-written vanilla JS

lower is better
  • vanilla JS×1.00
  • Meltea×1.12
  • React 18×5.86
› Show as a table
frameworkSlowdown against hand-written vanilla JS
vanilla JS×1.00
Meltea×1.12
React 18×5.86

Swapping two rows of 1,000 is two DOM moves in Meltea; React moves 998. A list re-renders only the rows whose item changed.

The whole picture

Time, size and memory in one figure.

Benchmark: within ×1.2 of hand-written JavaScript. js-framework-benchmark's keyed operations in headless Chrome, slowdown against vanilla JS, lower is better: vanilla 1.00, Meltea 1.15, Melact 1.17, React 18 1.70. JS bundle of the benchmark app, gzip: vanilla 1.4 kB, Meltea 9.0, Melact 9.9, React 18 45.6. Heap with 1,000 rows: vanilla 0.77 MB, Meltea 1.22, Melact 1.64, React 18 3.17. Swapping two rows of 1,000: Meltea 1.12, Melact 1.17, React 18 5.86

Whole apps

Small glasses.

Sizes of whole apps, gzip, with the runtime and the Melange stdlib they use included. Unused parts of the runtime drop out of the bundle.

Method

Measured the way js-framework-benchmark measures.

The four apps render the same markup and share one small inline stylesheet; the harness downloads nothing. Vanilla is hand-written keyed DOM code in the style of the benchmark's vanillajs-keyed; React is 18.3 with hooks, like the benchmark's react-hooks.
  • Every sample is a fresh tab: load, the benchmark's warmups for that operation, then one measured click, sent as real mouse input.
  • The measured click is traced. The time is the renderer main thread's busy time from the start of the click dispatch to the end of the first Paint and its Commit after it.
  • CPU slowdown as in the benchmark: 4× for partial update, select, swap and clear, 2× for remove.
  • After every measured click the page is checked: row count, every id in order, every label, the markup of every row, and which rows have class="danger". A fast but wrong result is reported, not counted silently.
  • Memory: two forced garbage collections, then the heap usage after creating 1,000 rows.
  • Size: the gzip (-9) size of all JS in the production bundle.