A Million A Minute, in a browser?
MILAMIN's 2008 headline: one million degrees of freedom per minute in native MATLAB, pre-processing, solving and post-processing included. This page runs the browser solver from this site on your machine, live, at increasing problem size, and plots assembly-plus-solution time.
The problem is the benchmark inclusion on unstructured Triangle meshes with the 7-node Crouzeix–Raviart element. The production pipeline, supernodal Cholesky (AMD), factorizes with CHOLMOD on an AMD fill-reducing ordering, compiled to WebAssembly. The opt-in comparison line, banded Cholesky (RCM), replaces only the factorization with a plain banded Cholesky in TypeScript on a reverse Cuthill–McKee ordering; mesh, element matrices, assembly and Powell–Hestenes iterations are the same code.
Reading the plot
Two references from MILAMIN 2008 are drawn. The star is Table 2's assembly-plus-solution time at one million velocity unknowns: 15 s for matrix computation and assembly plus 34 s for solution (AMD Opteron, MATLAB 2007a). The browser curves sum the same stages, element matrices and assembly, factorization and Powell–Hestenes iterations, so the star is the like-for-like point. The dashed grey curve is Figure 5 of the paper, the total time of the mechanical test problem against size; its scope is slightly wider, the paper calls the boundary conditions and post-processing minor, and it is the only reference that shows how the 2008 time grew with size: nearly straight in this log-log plot with a slope of about 1.1. The table below the plot also reports meshing and the broader pipeline total.
This is a historical comparison across different problems and machines. The 2008 test used a box with a circular hole and an inclusion ten times more viscous than the matrix under pure shear; this page uses a disc with an inclusion a thousand times more viscous under simple shear. Both counts include the bubble velocities, although this solver condenses them before global assembly. The speed-up quoted on the million page excludes meshing, rendering and initialization on both sides; that page separately shows its five-stage total. No historical time is extrapolated to another problem size.
The banded Cholesky line is off by default; enable "include banded Cholesky" to add it, up to 30 000 unknowns. It scales as n1.9, that is O(n·hbw²) with a bandwidth of about √n, so the gap to the supernodal solver widens rapidly: the right tool for demo-sized problems and the wrong tool for a million, which is precisely why the sparse backend exists.
The supernodal solver closes that gap with the very solver
MILAMIN used natively: CHOLMOD's supernodal Cholesky (the engine behind
MATLAB's chol) with a fill-reducing AMD ordering, compiled
to WebAssembly. The supernodal algorithm concentrates its flops in
dense matrix kernels, which this build vectorizes with wasm SIMD and,
on cross-origin isolated pages (this one included), spreads across
worker threads. On a 2013 desktop 1.4 million unknowns take about 34
seconds single-threaded and 23 seconds with four threads, and 2.8
million unknowns complete in about a minute inside wasm's 4 GB; the
status line below shows which build your browser is running. The same discrete
problem, the same Powell–Hestenes iterations, verified against the
banded solution to 10 digits; only the linear-solver backend differs.
The thread control defaults to four rather than to everything your
machine has: 2D factorizations are memory-bandwidth-bound and, as
the isoefficiency law in the 2011 notes predicts, more threads soon
stop helping and then hurt: in a controlled sweep a 2013 six-core
desktop peaked at four threads and lost 20% with all twelve, and a
2025 phone was fastest at two.
Numbers depend on your machine; the benchmark runs on yours, in a Web Worker. The largest setting allocates several GB and needs a 64-bit browser with memory to spare. What each stage is built on is on the how it works page.