Files
nushell/scripts
Darren Schroeder c123f61d7e feat(parser): add benchmarks for parser performance and throughput analysis (#18245)
<!--
Thanks for contributing to Nushell!

Before submitting, please read the contributing guide:
https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md

This template helps reviewers understand your changes and allows us to
generate high-quality release notes.
-->

## Description
This PR adds some parser benchmarks. See how to run them below. You
should get an output similar this below. Hopefully my math is right.
```nushell
Throughput summary (derived from benchmark timing, unit: micro):
╭────┬─────────────────────────────────────────┬───────┬───────┬─────────┬───────────┬────────────────┬────────────────╮
│  # │                benchmark                │ chars │ bytes │ seconds │ time_unit │ chars_per_unit │ bytes_per_unit │
├────┼─────────────────────────────────────────┼───────┼───────┼─────────┼───────────┼────────────────┼────────────────┤
│  0 │ parser_lex_large_97332b_97098c          │ 97098 │ 97332 │    0.00 │ micro     │         246.38 │         246.97 │
│  1 │ parser_lex_medium_4315b_4315c           │  4315 │  4315 │    0.00 │ micro     │         169.22 │         169.22 │
│  2 │ parser_lex_small_82b_82c                │    82 │    82 │    0.00 │ micro     │         106.11 │         106.11 │
│  3 │ parser_lite_medium_4315b_4315c          │  4315 │  4315 │    0.00 │ micro     │          95.46 │          95.46 │
│  4 │ parser_lite_real_world_620b_620c        │   620 │   620 │    0.00 │ micro     │          38.51 │          38.51 │
│  5 │ parser_lite_small_82b_82c               │    82 │    82 │    0.00 │ micro     │           5.99 │           5.99 │
│  6 │ parser_parse_block_medium_4315b_4315c   │  4315 │  4315 │    0.00 │ micro     │          37.52 │          37.52 │
│  7 │ parser_parse_block_real_world_620b_620c │   620 │   620 │    0.00 │ micro     │          24.31 │          24.31 │
│  8 │ parser_parse_block_small_82b_82c        │    82 │    82 │    0.00 │ micro     │           4.77 │           4.77 │
│  9 │ parser_parse_large_97332b_97098c        │ 97098 │ 97332 │    0.00 │ micro     │          97.10 │          97.33 │
│ 10 │ parser_parse_medium_4315b_4315c         │  4315 │  4315 │    0.00 │ micro     │          44.62 │          44.62 │
│ 11 │ parser_parse_small_82b_82c              │    82 │    82 │    0.00 │ micro     │           4.27 │           4.27 │
╰────┴─────────────────────────────────────────┴───────┴───────┴─────────┴───────────┴────────────────┴────────────────╯


Headline metric candidates (chars/micro):
╭───┬──────────────────────────────────┬────────────────╮
│ # │            benchmark             │ chars_per_unit │
├───┼──────────────────────────────────┼────────────────┤
│ 0 │ parser_lex_large_97332b_97098c   │         246.38 │
│ 1 │ parser_lex_medium_4315b_4315c    │         169.22 │
│ 2 │ parser_lex_small_82b_82c         │         106.11 │
│ 3 │ parser_parse_large_97332b_97098c │          97.10 │
│ 4 │ parser_lite_medium_4315b_4315c   │          95.46 │
╰───┴──────────────────────────────────┴────────────────╯


Benchmark logfile: target/parser-bench/benchmarks-parser__-20260519-125213.log
parser_lex_small_82b_82c                            [ 758.0 ns ... 772.8 ns ... 829.7 ns ]  stddev:  14.8 ns
parser_lex_medium_4315b_4315c                       [  25.2 us ...  25.5 us ...  26.1 us ]  stddev: 248.3 ns
parser_lex_large_97332b_97098c                      [ 389.0 us ... 394.1 us ... 410.0 us ]  stddev:   4.7 us
parser_lite_small_82b_82c                           [  13.2 us ...  13.7 us ...  17.7 us ]  stddev: 670.6 ns
parser_lite_medium_4315b_4315c                      [  45.0 us ...  45.2 us ...  46.0 us ]  stddev: 183.7 ns
parser_lite_real_world_620b_620c                    [  15.9 us ...  16.1 us ...  18.1 us ]  stddev: 374.2 ns
parser_parse_block_small_82b_82c                    [  16.7 us ...  17.2 us ...  19.0 us ]  stddev: 402.0 ns
parser_parse_block_medium_4315b_4315c               [ 111.0 us ... 115.0 us ... 124.3 us ]  stddev:   3.1 us
parser_parse_block_real_world_620b_620c             [  25.0 us ...  25.5 us ...  26.6 us ]  stddev: 411.2 ns
parser_parse_small_82b_82c                          [  18.7 us ...  19.2 us ...  20.8 us ]  stddev: 508.7 ns
parser_parse_medium_4315b_4315c                     [  95.2 us ...  96.7 us ... 113.4 us ]  stddev:   3.2 us
parser_parse_large_97332b_97098c                    [   1.0 ms ...   1.0 ms ...   1.0 ms ]  stddev:   3.8 us

   Compiling nu-cmd-lang v0.112.3 (/Users/fdncred/src/nushell/crates/nu-cmd-lang)
   Compiling nu-test-support v0.112.3 (/Users/fdncred/src/nushell/crates/nu-test-support)
   Compiling nu v0.112.3 (/Users/fdncred/src/nushell)
    Finished `bench` profile [optimized] target(s) in 1m 12s
     Running benches/benchmarks.rs (target/release/deps/benchmarks-5a8a0256451b1c57)
```
<!--
Explain what this PR does and why.

This section is intentionally flexible:
- Describe the problem
- Explain your approach
- Include technical details if relevant

Good examples:
- "In this PR, I fixed..."
- "In this PR, I added support for..."
- "This change improves X by..."

Write as much or as little as needed for reviewers to understand your
changes.
-->

## User-facing changes (Release notes)
Run the new parser benchmarks like this:
```nushell
nu scripts/parser-bench-run.nu
```
The `parser-bench-run.nu` script has these arguments.
```nushell
    --filter: string = "parser_*"   # benchmark name glob filter (tango uses glob matching)
    --bench: string = "benchmarks"  # bench target name
    --out-dir: path = "target/parser-bench"  # directory where logs are written
```

Analyze the new parser benchmarks like this:
```nushell
nu scripts/parser-bench-throughput.nu target/parser-bench/benchmarks-parser__-20260519-125213.log
```
The `parser-bench-throughput.nu` script has these arguments
```nushell
    log_file?: path   # output file produced by parser-bench-0.112.2-run.nu
    --name-prefix: string = "parser_" # benchmark name glob filter
    --time-unit: string = "micro"  # throughput time base: sec|milli|micro|nano
```
<!--
This section is used (mostly as-is) for https://www.nushell.sh/blog/

Describe how Nushell behavior changes from a user's perspective.
Do NOT describe internal Rust changes here.

Write in a release note style, for example:
- "Added support for..."
- "Fixed an issue where..."
- "Nushell now supports..."
- "Improved performance of..."

If your changes do NOT affect users (internal refactors, cleanup, etc.),
just write:
- "n/a"
- "nan"
- or similar

This tells us the change should not appear in the changelog.

Tips:
- Focus on observable behavior
- Include examples if helpful
- Keep it concise

You can:
- Write a short paragraph (will appear as a bullet point), OR
- Use headings (###) if your change needs more structure

Avoid writing things like:
- "In this PR, I refactored..."
- "This updates internal code..."

You may leave this blank until the PR is ready.
-->

## Additional notes
<!--
Optional.

Examples:
- fixes #123
- closes #456
- related #789

Anything else reviewers should know.
Remove this section if not needed.
-->
2026-05-19 15:58:47 -05:00
..

run the scripts

Note


the following table must be read as follows:

  • an x means it works
  • a ? means no data available

.nu scripts must be run as nu .../foo.nu
.sh scripts must be run as ./.../foo.sh
.ps1 scripts must be run as powershell .../foo.ps1

let's say a script is called foo

  • an x in the ./scripts column means foo can be run from ./scripts
  • an x in the root column means foo can be run from the root of nushell
  • an x in the anywhere column means foo can be run from anywhere!
script ./scripts/ root anywhere
build-all-maclin.sh x x x
build-all-windows.cmd ? x ?
build-all.nu x x x
coverage-local.nu x x x
coverage-local.sh x x x
install-all.ps1 ? x ?
install-all.sh x x x
uninstall-all.sh x x x