F# HTML DSL benchmarks for deeply nested pages - Falco.Markup vs Giraffe.ViewEngine vs Feliz.ViewEngine

Date: 2024-02-12 | create | tech | fsharp | html | benchmarks | giraffe | falco | feliz |

Last week we benchmarked F# HTML DSLs for rendering long HTML pages. This is useful if you're building pages with very large lists or tables. But this is a relatively rare occurrence IRL as you'll usually split up large pages with pagination or dynamic node rendering based on visibility.

A more common paradigm is to render deeply nested pages. If we think of a sufficiently mature / complex web page, it typically consists of several components - each of which is an Interactive Island. What this means is that we often have several sections of dense and deeply nested HTML trees on our page with none-few sections longer than 100 elements.

Previous deeply nested page benchmark revealed severe perf issues with raw string HTML rendering for deeply nested pages when compared to HTML DSLs (a difference of 1700x at scale). So in this post we'll be comparing how different HTML DSLs stack up for this workload.

Benchmark Setup

F# HTML DSL Benchmarks - Deeply Nested Pages

In this benchmark, we build a simple HTML page containing a series of n nested divs from size 10 to 5000. Each div contains text containing its index and the next nested div.

Benchmarks are run and aggregated with BenchmarkDotnet on a free Replit instance.

You can access the code and run the benchmark yourself on Replit - F# HTML DSL - deeply nested page benchmarks Replit

Results Overview

F# HTML DSL Benchmarks - Perf Graph

Falco.Markup and Giraffe.ViewEngine show very similar performance profiles throughout the workloads. Falco.Markup generally wins by a small fraction (< 10%) with the absolute difference coming out to tenths of a millisecond.

Both outperform Feliz.ViewEngine by about 3x with absolute differences in the 1-10 milliseconds range.

Detailed Results

F# HTML DSL Benchmarks - Perf Table

In this section I'll share the raw results for posterity.

10 items

10 Items

  • Falco.Markup: 0.007 ms
  • Giraffe.Viewengine: 0.008 ms
  • Feliz.ViewEngine: 0.03 ms

100 items

100 items

  • Falco.Markup: 0.063 ms
  • Giraffe.ViewEngine: 0.062 ms
  • Feliz.ViewEngine: 0.264 ms

1000 items

1000 items

  • Falco.Markup: 0.908 ms
  • Giraffe.ViewEngine: 0.943 ms
  • Feliz.ViewEngine: 3.152 ms

2000 items

2000 items

  • Falco.Markup: 1.765 ms
  • Giraffe.ViewEngine: 1.987 ms
  • Feliz.ViewEngine: 6.651 ms

5000 items

5000 items

  • Falco.Markup: 4.72 ms
  • Giraffe.ViewEngine: 4.716 ms
  • Feliz.ViewEngine: 18.018 ms

Next

Overall Giraffe.ViewEngine and Falco.Markup perform very well and are pretty easy to work with so would recommend those for your HTML DSL rendering needs. Feliz.ViewEngine is still pretty fast but coupling its relative slowness with its kinda clunky API and lack of recent updates makes it seem a less attractive choice from my perspective.

If you have suggestions for other HTML DSLs you'd like benchmarked, send them my way! Every time I publish one of these I discover new ones people are using.

If you liked this post, you might also like:

Want more like this?

The best / easiest way to support my work is by subscribing for future updates and sharing with your network.