{"id":51423955,"url":"https://github.com/gampleman/elm-bench","last_synced_at":"2026-07-05T01:30:38.809Z","repository":{"id":357824477,"uuid":"1238700154","full_name":"gampleman/elm-bench","owner":"gampleman","description":"Rich Elm benchmarking with a powerful CLI runner","archived":false,"fork":false,"pushed_at":"2026-05-20T14:46:15.000Z","size":184,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-17T20:09:31.432Z","etag":null,"topics":["benchmarking","elm"],"latest_commit_sha":null,"homepage":"https://package.elm-lang.org/packages/gampleman/elm-bench/latest/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gampleman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T11:17:07.000Z","updated_at":"2026-05-22T00:58:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gampleman/elm-bench","commit_stats":null,"previous_names":["gampleman/elm-bench"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/gampleman/elm-bench","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gampleman%2Felm-bench","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gampleman%2Felm-bench/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gampleman%2Felm-bench/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gampleman%2Felm-bench/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gampleman","download_url":"https://codeload.github.com/gampleman/elm-bench/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gampleman%2Felm-bench/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35141083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmarking","elm"],"created_at":"2026-07-05T01:30:38.125Z","updated_at":"2026-07-05T01:30:38.790Z","avatar_url":"https://github.com/gampleman.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# elm-bench\n\nA complete benchmarking toolkit for Elm. Define benchmarks with automatic correctness verification, run them headlessly across multiple JS engines, and get rich terminal output with scaling charts.\n\n## The Experience\n\n**Define benchmarks with a clean API:**\n\n```elm\nmodule MyBenchmarks exposing (suite)\n\nimport Bench exposing (Benchmark)\n\nsuite : Benchmark\nsuite =\n    Bench.describe \"Array.Extra\"\n        [ Bench.rank \"mapToList\"\n            (\\mapToList -\u003e mapToList negate myArray)\n            [ ( \"with foldr\", MapToList.withFoldr )\n            , ( \"with toIndexedList\", MapToList.withListMap )\n            ]\n        , Bench.scale \"mapToList across sizes\"\n            [ 10, 100, 1000, 10000 ]\n            (\\n -\u003e Array.fromList (List.range 1 n))\n            [ ( \"with foldr\", MapToList.withFoldr negate )\n            , ( \"with toIndexedList\", MapToList.withListMap negate )\n            ]\n        ]\n```\n\n**Run with a single command:**\n\n```\n$ elm-bench run --filter mapToList\n```\n\n**Get verification first, then results:**\n\n```\nVerifying benchmark correctness...\n\n  ✓ All implementations produce consistent results\n\nSeed: 1847293651  (reproduce with --seed 1847293651)\n\nRunning benchmarks in node...\n\nBenchmark Results\n\n  Array.Extra / mapToList\n  ───────────────────────────────────────────────────────\n  with foldr                980,124 runs/s      (99.9%)     fastest\n  with Array.toIndexedList  535,891 runs/s      (99.8%)     1.83x slower\n```\n\n**See how algorithms scale with input size:**\n\n```\n  Array.Extra / mapToList across sizes\n\n   30.2M ┼──╮───╮\n   17.5M ┤  ╰─────╮─────╮\n   10.1M ┤        ╰─────╮────╮\n    5.8M ┤             ╰────╮────╮\n    3.4M ┤                  ╰────╮────╮\n    1.9M ┤                       ╰────╮────╮\n    1.1M ┤                            ╰────╮────╮\n  651.3K ┤                                 ╰────╮───╮\n  376.5K ┤                                      ╰───╮───╮\n  217.6K ┤                                          ╰───╮───╮\n  125.8K ┤                                              ╰───╮──╮\n   72.7K ┤                                                  ╰──╮──╮\n   42.0K ┤                                                     ╰──╮──╮\n   24.3K ┤                                                        ╰──╮──╮\n   14.0K ┤                                                           ╰──╮──\n    8.1K ┤                                                              ╰──╮\n    4.7K ┤                                                                 ╰\n         (log scale)\n      n= 1              10                            500  1000         10000\n\n  ━━ with foldr  (30.2M → 9.8K runs/s)\n  ━━ with Array.toIndexedList  (23.0M → 4.7K runs/s)\n```\n\nIn terminals with inline image support (iTerm2, WezTerm, Ghostty, VS Code), a full-color PNG chart is rendered instead.\n\n**Compare across JavaScript engines:**\n\n```\n$ elm-bench run -t node -t chromium -t firefox --filter mapToList\n\n  Array.Extra / indexedMapToList\n                         node              chromium          firefox\n  ────────────────────────────────────────────────────────────────────\n  with Array.foldr       608,609 runs/s    712,445 runs/s    838,702 runs/s\n  with Array.indexedMap  527,083 runs/s    634,221 runs/s    671,752 runs/s\n  with List.indexedMap   384,174 runs/s    445,890 runs/s    339,777 runs/s\n  with toIndexedList     302,367 runs/s    356,112 runs/s    330,534 runs/s\n```\n\nWhen rankings differ across targets, entries are highlighted in green (ranked higher than first target) or red (ranked lower) — immediately surfacing cross-engine performance characteristics.\n\n## Quick Start\n\n```bash\ncd my-project\nnpx elm-bench init\n```\n\nThis creates a `benchmarks/` directory with `elm.json` (with `gampleman/elm-bench` installed) and a starter `Benchmarks.elm` file.\n\nThen run your benchmarks:\n\n```bash\nelm-bench run\n```\n\n## Installation\n\n```bash\nnpm install -g elm-bench\n```\n\nOr as a project dependency:\n\n```bash\nnpm install --save-dev elm-bench\n```\n\n## Key Features\n\n### Automatic Correctness Verification\n\n`Bench.rank`, `Bench.compare`, and `Bench.scale` automatically verify that all implementations produce the same result before benchmarking begins. This runs via `elm-test-rs` in seconds and catches broken optimizations before you waste time on misleading benchmark results.\n\n```\nVerifying benchmark correctness...\n\n  ✗ Benchmark verification failed!\n\n  Some implementations produce different results:\n\n    ↓ Array.Extra / reverse\n    ✗ with List.reverse should match with push\n        Array.fromList [100,99,...,1]\n        ╷\n        │ Expect.equal\n        ╵\n        Array.fromList [1,2,...,100]\n```\n\nUse `Bench.skipEqualityCheck` for cases where implementations intentionally differ (e.g. different valid orderings).\n\n### Optimization Workflow\n\nScaffold a head-to-head comparison for any function in your project:\n\n```bash\nelm-bench optimize MyModule.myFunction --arg \"(List.range 1 1000)\"\n```\n\nThis:\n\n1. Copies `MyModule` into `Baseline` and `Optimized` variants (with dead code removed)\n2. Generates a `Bench.rank` benchmark comparing them\n3. You edit the `Optimized` copy and iterate\n\nAdd more variants to compare:\n\n```bash\nelm-bench optimize MyModule.myFunction --add Experimental\n```\n\nUse `--watch` for instant feedback as you edit:\n\n```bash\nelm-bench run --watch\n```\n\n### Filtering\n\nOnly run what you need:\n\n```bash\nelm-bench run --filter mapToList\n```\n\nFiltering happens at the Elm level before benchmarks execute — so even with hundreds of benchmarks in your suite, filtered runs are fast.\n\n### Fuzzer-Based Inputs\n\nUse `elm-explorations/test` fuzzers for randomized benchmark input:\n\n```elm\nBench.rankFuzz \"mapToList\"\n    (Fuzz.array (Fuzz.intRange 1 1000))\n    (\\mapToList array -\u003e mapToList negate array)\n    [ ( \"with foldr\", MapToList.withFoldr )\n    , ( \"with toIndexedList\", MapToList.withListMap )\n    ]\n```\n\nThe same fuzzer is used for both the correctness check (fuzz test) and to generate the benchmark input (seeded deterministically via `--seed`). The seed is printed with every run so you can reproduce results.\n\n#### Debugging Fuzzer Inputs\n\nIf you see unexpected benchmark results and want to know what input the fuzzer generated, copy the seed from the output and use `Bench.sampleFuzzer` in `elm repl`:\n\n```\n\u003e import Bench\n\u003e import Fuzz\n\u003e Bench.sampleFuzzer 1847293651 (Fuzz.list (Fuzz.intRange 1 100))\nJust [42, 7, 93, ...] : Maybe (List Int)\n```\n\nThis gives you the exact value the fuzzer produced during that run.\n\n### Multi-Target Execution\n\nCompare across JavaScript engines to ensure optimizations are consistent:\n\n```bash\nelm-bench run -t node -t chromium -t firefox -t webkit\n```\n\nRequires Playwright for browser targets: `npm install playwright`.\n\n### Scaling Analysis\n\nUnderstand algorithmic complexity with `Bench.scale`:\n\n```elm\nBench.scale \"sorting\"\n    [ 10, 100, 1000, 10000 ]\n    (\\n -\u003e List.range 1 n |\u003e List.reverse)\n    [ ( \"List.sort\", List.sort )\n    , ( \"mergeSort\", mergeSort )\n    ]\n```\n\nResults are rendered as a chart with automatic log-scale detection.\n\n### Output Formats\n\n- **console** (default) — colored terminal output with progress bars and charts\n- **json** — machine-readable for CI integration\n- **markdown** — GitHub-flavored tables for easy paste into PRs\n\n```bash\nelm-bench run --reporter markdown\n```\n\n## CLI Reference\n\n```\nelm-bench init [options]\n  Initialize a benchmarks directory with elm-bench installed.\n  --project \u003cpath\u003e         Base directory to create benchmarks/ in\n\nelm-bench run [options] [globs...]\n  Run benchmarks.\n  -f, --filter \u003cpattern\u003e   Only run benchmarks matching pattern\n  -t, --target \u003cname\u003e      Execution target (repeatable): node, chromium, firefox, webkit\n  -r, --reporter \u003cformat\u003e  Output: console (default), json, markdown\n  --compiler \u003cpath\u003e        Path to elm binary\n  --project \u003cpath\u003e         Path to benchmarks elm.json\n  --seed \u003cnumber\u003e          Random seed for fuzz-based inputs\n  --skip-test              Skip correctness verification\n  --no-optimize            Disable --optimize (for debugging)\n  -w, --watch              Watch for changes and re-run affected benchmarks\n\nelm-bench optimize \u003cModule.function\u003e [options]\n  Scaffold an optimization comparison benchmark.\n  --add \u003cname\u003e             Add a new variant to an existing optimization\n  --arg \u003cexpr\u003e             Argument expression for the runner (repeatable)\n  --project \u003cpath\u003e         Path to elm.json\n```\n\n## Requirements\n\n- Node.js \u003e= 18\n- Elm 0.19.1 (bundled with CLI)\n- For browser targets: `npm install playwright`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgampleman%2Felm-bench","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgampleman%2Felm-bench","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgampleman%2Felm-bench/lists"}