LALOLib

Benchmark for linear algebra javascript libraries

Features

This table compares the features offered by different javascript libraries for linear algebra (see below for performance).

Library High-level language parser Plots Matlab-like development environment Background computing Matrix factorizations Linear system solver Sparse linear algebra Statistics Optimization Other
LALOLib Yes Yes Yes Yes Cholesky, QR, eigen-decomposition, SVD Yes Yes Yes (sample, estimate, pdf for (mv)Gaussian, uniform, Poisson, Bernoulli distributions) Steepest descent, BFGS, linear programming (with glpk.js), quadratic programming Complex numbers, fast Fourier transform
math.js Yes No Yes No LU Square nonsingular systems only Basic support only Sample from Gaussian and uniform distributions No Complex numbers
numeric.js Yes Yes Yes No LU, eigen-decomposition, SVD Square nonsingular systems only Yes No Unconstrained minimization, linear programming, quadratic programming Complex numbers, ODE solver
Sushi No No No No QR, SVD No No No No

Note: we compare with the simple Sushi library, not SushiCL which uses GPU accelaration but requires a much more complex installation step for the users.



Performance

The next table compares the performance of the libraries and displays the computing time in milliseconds of standard linear algebra operations.

Library Creating large random matrices Matrix multiply Square linear systems Least squares / overdetermined linear system Sparse least squares Singular value decomposition Eigen-decomposition
LALOLib 59 429 98 667 (error = 0.05) 235 272 24
math.js 151 3854 1179 > 12000 N/A N/A N/A
numeric.js 1923 1420 158 10905 (error = 0.05) N/A 484 6661
Sushi 73 545 577 (error = 4.4e+2) 1751 (error = 8.4) N/A 388 (error = 1.2) N/A

These results were obtained with Firefox 41 running on Ubuntu with an Intel i7-3540M CPU at 3.00GHz. Note that different results can be obtained with different browsers (click on the 'Run' buttons to try with yours). For instance, numeric.js performs much faster with Chrome.

A few observations:

  • math.js and numeric.js can be slower because they use an Array of Arrays representation of matrices instead of a single Typed Array. While this provides easy access to the entries of A with A[i][j], it has two major issues. First, operations on Arrays are not easily optimized by the browser, since the size of the Array can change and its entries are not typed. Second, for each row, this creates an Array, which is a complex object that must be handled by the garbage collector. As a result, a matrix with many rows implies significant slow downs at every garbage collection cycle.
    In addition, math.js and numeric.js do not provide dedicated functions for rectangular systems and we have to explicitly form the square system (A'A)x = A'b and solve it. This also means that the sparse linear system solver of numeric.js cannot be used for least squares problems, since A'A is typically not sparse even with a sparse A.
  • Sushi can be fast but also less accurate. It uses 32-bits floats (Float32Array) instead of 64 bits. Default tolerance constants are also set to large values, in particular for the SVD, which yields a non-valid matrix factorization. In addition, Sushi does not provide functions for solving linear systems (square systems are solved via explicit matrix inversion).