Add PNG graphics to perf docs for issue-2084 perf mods (#2095)

* perf how-to

* PNG files to docs
This commit is contained in:
John Kerl 2026-06-20 10:39:43 -04:00 committed by GitHub
parent 88286fd1b4
commit 88950fd90b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 181 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -83,6 +83,10 @@ The table below compares wall-clock time before and after these changes, using t
| `put` UDF-heavy | 2.81s | 1.71s | -39% |
| `put` map-returning UDF | 2.72s | 1.92s | -29% |
![perf/2026-06-20-verbs.png](perf/2026-02-22-verbs.png)
![perf/2026-06-20-cats.png](perf/2026-06-20-cats.png)
![perf/2026-06-20-chains.png](perf/2026-06-20-chains.png)
Peak resident set size (RSS) for representative workloads:
| Workload | Before | After | Change |

View file

@ -67,6 +67,10 @@ The table below compares wall-clock time before and after these changes, using t
| `put` UDF-heavy | 2.81s | 1.71s | -39% |
| `put` map-returning UDF | 2.72s | 1.92s | -29% |
![perf/2026-06-20-verbs.png](perf/2026-02-22-verbs.png)
![perf/2026-06-20-cats.png](perf/2026-06-20-cats.png)
![perf/2026-06-20-chains.png](perf/2026-06-20-chains.png)
Peak resident set size (RSS) for representative workloads:
| Workload | Before | After | Change |

78
scripts/perf/README.md Normal file
View file

@ -0,0 +1,78 @@
# Miller Performance Benchmarks
Scripts for reproducing the performance graphs at
https://miller.readthedocs.io/en/latest/performance/
## Quick start
```
# Once — if ~/data/big.csv doesn't already exist (run from repo root):
bash scripts/perf/prep-perf-data.sh
# Collect timings and render graphs (run from scripts/perf/):
cd scripts/perf
bash run-perf.sh ~/bin/mlr-6.18.1 ~/bin/mlr-6.19.0
```
That runs `time-verbs.py` with both executables (5 reps each, ~18 cases),
saves `timings-YYYY-MM-DD.dat`, then calls `plot-timings.sh` to produce three
PNGs: `-verbs.png`, `-chains.png`, `-cats.png`.
## Prerequisites
- Python 3
- [`pgr`](https://github.com/johnkerl/pgr) (used by `plot-timings.sh` to render PNG graphs)
- One or more Miller executables to compare
## Step-by-step
### Step 1 — Generate test data (one-time)
Run from the Miller repo root:
```
bash scripts/perf/prep-perf-data.sh
```
This creates `~/data/big.csv` (~1 million rows) and derived files in DKVP,
NIDX, XTAB, and JSON formats, plus `small.csv` and `medium.csv` subsets.
### Step 2 — Collect timings
Run from `scripts/perf/`, passing one or more executables to compare:
```
python time-verbs.py ~/bin/mlr-6.18.1 ~/bin/mlr-6.19.0 \
> timings-$(date +%Y-%m-%d).dat
```
Output is DKVP, one record per (case, executable): `desc=...,version=...,seconds=...`
Five reps are averaged per case. Cases cover:
- **Verbs**: `check`, `cat`, `tail`, `tac`, `sort -f`, `sort -n`, `stats1`
- **Then-chains**: one to four chained `put -f chain-1.mlr` steps
- **Formats**: `cat` across CSV, CSVLITE, DKVP, NIDX, XTAB, JSON
### Step 3 — Plot
```
bash plot-timings.sh timings-YYYY-MM-DD.dat
```
Produces three PNGs alongside the dat file:
- `*-verbs.png` — verb timings
- `*-chains.png` — then-chain depth
- `*-cats.png` — format comparison
## Files
| File | Purpose |
|------|---------|
| `prep-perf-data.sh` | Generate `~/data/big.csv` and format variants (one-time) |
| `time-verbs.py` | Time each verb/format/chain case; outputs DKVP |
| `chain-1.mlr` | DSL script used for then-chain benchmarks |
| `run-perf.sh` | Wrapper: collect timings + plot |
| `plot-timings.sh` | Read a `.dat` file and render PNGs via `pgr` |
| `timings-2026-02-22.sh` | Original one-off plot script (hardcoded filename) |
| `timings-2026-02-22.dat` | Timing data from the February 2026 run |

30
scripts/perf/plot-timings.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/bash
# Usage: plot-timings.sh timings.dat
# Requires: mlr, pgr
# Run from the Miller repo root.
set -e
datafile="${1:?Usage: $0 timings.dat}"
stem="${datafile%.dat}"
mlr --d2p --from "$datafile" \
grep cat then reshape -s desc,seconds \
| sed '1s/^/#/' \
| pgr -cat -ymin 0 -flabels -lur -lp -ms 5 -o "${stem}-cats.png" &
mlr --d2p --from "$datafile" \
grep chain then reshape -s desc,seconds \
| sed '1s/^/#/' \
| pgr -cat -ymin 0 -flabels -lur -lp -ms 5 -o "${stem}-chains.png" &
mlr --d2p --from "$datafile" \
grep -v cat then grep -v chain then reshape -s desc,seconds \
| sed '1s/^/#/' \
| pgr -cat -ymin 0 -flabels -lur -lp -ms 5 -o "${stem}-verbs.png" &
wait
echo "Plots written:"
echo " ${stem}-cats.png"
echo " ${stem}-chains.png"
echo " ${stem}-verbs.png"

22
scripts/perf/run-perf.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
# Usage: run-perf.sh mlr-executable [mlr-executable ...]
# Run from scripts/perf/.
set -e
dir="$(cd "$(dirname "$0")" && pwd)"
if [ $# -eq 0 ]; then
echo "Usage: $0 mlr-executable [mlr-executable ...]" >&2
echo "Example: $0 ~/bin/mlr-6.18.1 ~/bin/mlr-6.19.0" >&2
exit 1
fi
datfile="timings-$(date +%Y-%m-%d).dat"
echo "Collecting timings into $datfile ..."
python "$dir/time-verbs.py" "$@" | tee "$datfile"
echo ""
echo "Generating plots ..."
bash "$dir/plot-timings.sh" "$datfile"

View file

@ -5,6 +5,9 @@ import sys
import time
import subprocess
script_dir = os.path.dirname(os.path.abspath(__file__))
chain_mlr = os.path.join(script_dir, "chain-1.mlr")
# ================================================================
def main():
mlrs = [ "mlr" ]
@ -28,10 +31,10 @@ def main():
["sort-n", f"--csv --from {in_csv} sort -n quantity"],
["stats1", f"--csv --from {in_csv} stats1 -a min,mean,max -f quantity,rate -g shape"],
None,
["chain-1", f"--csv --from {in_csv} put -f scripts/perf/chain-1.mlr"],
["chain-2", f"--csv --from {in_csv} put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr"],
["chain-3", f"--csv --from {in_csv} put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr"],
["chain-4", f"--csv --from {in_csv} put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr then put -f scripts/perf/chain-1.mlr"],
["chain-1", f"--csv --from {in_csv} put -f {chain_mlr}"],
["chain-2", f"--csv --from {in_csv} put -f {chain_mlr} then put -f {chain_mlr}"],
["chain-3", f"--csv --from {in_csv} put -f {chain_mlr} then put -f {chain_mlr} then put -f {chain_mlr}"],
["chain-4", f"--csv --from {in_csv} put -f {chain_mlr} then put -f {chain_mlr} then put -f {chain_mlr} then put -f {chain_mlr}"],
None,
["cat-csv", f"--csv --from {in_csv} cat"],
["cat-csvlite", f"--csvlite --from {in_csvlite} cat"],

View file

@ -0,0 +1,36 @@
desc=check,version=mlr-6.18.1,seconds=0.614
desc=check,version=mlr-6.19.0,seconds=0.217
desc=cat,version=mlr-6.18.1,seconds=0.620
desc=cat,version=mlr-6.19.0,seconds=0.223
desc=tail,version=mlr-6.18.1,seconds=0.606
desc=tail,version=mlr-6.19.0,seconds=0.210
desc=tac,version=mlr-6.18.1,seconds=1.066
desc=tac,version=mlr-6.19.0,seconds=0.463
desc=sort-f,version=mlr-6.18.1,seconds=1.120
desc=sort-f,version=mlr-6.19.0,seconds=0.521
desc=sort-n,version=mlr-6.18.1,seconds=2.696
desc=sort-n,version=mlr-6.19.0,seconds=2.008
desc=stats1,version=mlr-6.18.1,seconds=0.678
desc=stats1,version=mlr-6.19.0,seconds=0.549
desc=chain-1,version=mlr-6.18.1,seconds=1.052
desc=chain-1,version=mlr-6.19.0,seconds=0.719
desc=chain-2,version=mlr-6.18.1,seconds=1.096
desc=chain-2,version=mlr-6.19.0,seconds=0.759
desc=chain-3,version=mlr-6.18.1,seconds=1.188
desc=chain-3,version=mlr-6.19.0,seconds=0.881
desc=chain-4,version=mlr-6.18.1,seconds=1.357
desc=chain-4,version=mlr-6.19.0,seconds=0.959
desc=cat-csv,version=mlr-6.18.1,seconds=0.638
desc=cat-csv,version=mlr-6.19.0,seconds=0.233
desc=cat-csvlite,version=mlr-6.18.1,seconds=0.703
desc=cat-csvlite,version=mlr-6.19.0,seconds=0.289
desc=cat-dkvp,version=mlr-6.18.1,seconds=0.949
desc=cat-dkvp,version=mlr-6.19.0,seconds=0.462
desc=cat-nidx,version=mlr-6.18.1,seconds=2.058
desc=cat-nidx,version=mlr-6.19.0,seconds=1.559
desc=cat-xtab,version=mlr-6.18.1,seconds=0.767
desc=cat-xtab,version=mlr-6.19.0,seconds=1.305
desc=cat-json,version=mlr-6.18.1,seconds=7.890
desc=cat-json,version=mlr-6.19.0,seconds=7.512