haskell-benchmarkinglisted
Install: claude install-skill ivelten/claude-haskell-skills
# Haskell Benchmarking
Default stack: **`tasty-bench`** for timing + **`weigh`** for allocation. Use `criterion` only when you specifically need its HTML reports.
Benchmarks live in a dedicated `benchmark` cabal stanza, separate from tests, and are run with `cabal bench` (not `cabal test`). Don't mix the two — tests are correctness gates that run on every commit; benchmarks are observability tools that run on demand or nightly because their variance is too high to gate builds.
## Cabal stanza
Place benchmarks in `bench/` next to `src/` and `test/`. Compile with `-O2` always — benchmarking `-O0` code measures nothing useful.
```cabal
benchmark my-project-bench
import: shared
type: exitcode-stdio-1.0
hs-source-dirs: bench
main-is: Bench.hs
ghc-options: -O2
build-depends:
, base
, my-project
, tasty-bench ^>=0.4
, weigh ^>=0.0.17
```
Run with `cabal bench` (or `cabal bench my-project-bench` to target a specific stanza).
## Timing benchmarks with `tasty-bench`
```haskell
module Main (main) where
import Test.Tasty.Bench
import qualified Data.Map.Strict as Map
import qualified Data.IntMap.Strict as IntMap
main :: IO ()
main = defaultMain
[ bgroup "lookup"
[ bench "Map.lookup @1000" $ nf (Map.lookup 500) mapData
, bench "IntMap.lookup @1000" $ nf (IntMap.lookup 500) intMapData
]
, bgroup "insert"
[ bench "Map.insert @1000" $ nf (Map.insert 1001 ()) map