Performance
What a forecast costs. Accuracy comparisons live on the benchmarks page; this is the runtime axis, measured on one machine with every model given the same core budget. There are two regimes and they disagree, so both are reported.
Streaming: one new observation arrives
laplace is online. A new observation costs a single state update
whose cost does not depend on how much history preceded it. A foundation model
carries no state, so it re-runs its whole forward pass over a shifted window
every time. This is the regime a live deployment runs in.
| model | ms per observation | vs laplace (Rust) k=1 |
|---|---|---|
| laplace (Rust) k=12 | 0.1511 | 12× |
| laplace (Python) k=1 | 0.2506 | 20× |
| AutoETS (refit) | 1.9310 | 157× |
| Chronos-Bolt-small | 7.4397 | 604× |
| Prophet (refit) | 29.9660 | 2,434× |
| AutoARIMA (refit) | 62.1336 | 5,047× |
| TiRex | 95.6831 | 7,772× |
| TimesFM-2.5-200M | 329.8290 | 26,792× |
Batch: one forecast for a series never seen before
This is the benchmark protocol, and it is laplace at its worst: it must consume the whole history to warm up, while a foundation model amortises a batched forward pass across many series. Best batch size shown per model.
| model | ms per series | regime |
|---|---|---|
| Chronos-Bolt-small | 0.7215 | cold b=64 |
| AutoETS (refit) | 1.9310 | cold |
| laplace (Rust) k=1 | 3.3897 | cold |
| TimesFM-2.5-200M | 5.0996 | cold b=64 |
| Prophet (refit) | 29.9660 | cold |
| laplace (Rust) k=12 | 42.6171 | cold |
| AutoARIMA (refit) | 62.1336 | cold |
| laplace (Python) k=1 | 67.0809 | cold |
| TiRex | 74.9486 | cold b=16 |
Every measurement
| model | regime | ms | note |
|---|---|---|---|
| laplace (Rust) k=1 | cold | 3.3897 | replays 256 points |
| laplace (Rust) k=1 | warm | 0.0123 | one online update |
| laplace (Rust) k=12 | cold | 42.6171 | replays 256 points |
| laplace (Rust) k=12 | warm | 0.1511 | one online update |
| laplace (Python) k=1 | cold | 67.0809 | replays 256 points |
| laplace (Python) k=1 | warm | 0.2506 | one online update |
| Chronos-Bolt-small | cold b=1 | 7.4409 | 48M params, batched |
| Chronos-Bolt-small | cold b=16 | 1.2924 | 48M params, batched |
| Chronos-Bolt-small | cold b=64 | 0.7215 | 48M params, batched |
| Chronos-Bolt-small | warm | 7.4397 | stateless: full re-forward |
| TiRex | cold b=1 | 96.4729 | 35M params, xLSTM, batched |
| TiRex | cold b=16 | 74.9486 | 35M params, xLSTM, batched |
| TiRex | cold b=64 | 76.3377 | 35M params, xLSTM, batched |
| TiRex | warm | 95.6831 | stateless: full re-forward |
| Sundial-base-128m | cold | n/a | unavailable: AttributeError: 'DynamicCache' object has no attribute 'seen_tokens' |
| TimesFM-2.5-200M | cold b=1 | 323.4401 | 200M params, batched |
| TimesFM-2.5-200M | cold b=16 | 20.2639 | 200M params, batched |
| TimesFM-2.5-200M | cold b=64 | 5.0996 | 200M params, batched |
| TimesFM-2.5-200M | warm | 329.8290 | stateless: full re-forward |
| AutoARIMA (refit) | cold | 62.1336 | fit on 256 points |
| AutoARIMA (refit) | warm | 62.1336 | refits from scratch every step |
| AutoETS (refit) | cold | 1.9310 | fit on 256 points |
| AutoETS (refit) | warm | 1.9310 | refits from scratch every step |
| Prophet (refit) | cold | 29.9660 | fit on 256 points |
| Prophet (refit) | warm | 29.9660 | refits from scratch every step |
Caveats
- CPU only, 1 torch thread. A GPU changes the foundation-model numbers substantially and does not change laplace's.
- The two regimes disagree, and neither is wrong. Batched, a foundation model can be cheaper per series than laplace replaying a history. Streaming, laplace is orders of magnitude cheaper. Which number applies depends entirely on whether you are scoring a benchmark or running a service.
- Rust and Python differ by roughly 18×. Ratios here are
against the Rust core (
skaters_fast), which is what ships; the pure-Python reference is correspondingly slower. - Horizon costs laplace. Going from k=1 to k=12 costs it roughly an order of magnitude, because the multi-scale ensemble runs a full candidate pool per decimation stride per horizon.
- Not size-ordered. The models differ in parameter count and in output mechanism (quantile heads versus sampled paths), so this ranks implementations as configured, not architectures in the abstract.
- Dependencies are not in the table. laplace is pure Python (and JavaScript, and Rust) with no weights to download and runs in a browser; the foundation models need torch and hundreds of megabytes of weights.
Reproducing this
Every number on this page is generated, not typed. The script measures each model and writes both this page and the machine-readable results beside it, so re-running it refreshes the page and nothing here can drift from the data.
PYTHONPATH=src:benchmarks python benchmarks/perf_compare.py
perf_compare.py — the measurement script · perf_results.json — these numbers as data
Knobs, as environment variables: PERF_L context length,
PERF_H horizon, PERF_N series count,
TORCH_THREADS core budget for the neural models. Each model is warmed
up before timing and reported as the median of repeats.
Measured 2026-08-12 on Darwin arm64, Python 3.11.15, skaters 0.16.0+8ddc8d5, context 256 points, horizon 12, 64 series, median of repeats.