mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-17 16:38:54 +00:00
Add PNG graphics to perf docs for issue-2084 perf mods (#2095)
* perf how-to * PNG files to docs
This commit is contained in:
parent
88286fd1b4
commit
88950fd90b
10 changed files with 181 additions and 4 deletions
BIN
docs/src/perf/timings-2026-06-20-cats.png
Normal file
BIN
docs/src/perf/timings-2026-06-20-cats.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/src/perf/timings-2026-06-20-chains.png
Normal file
BIN
docs/src/perf/timings-2026-06-20-chains.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
docs/src/perf/timings-2026-06-20-verbs.png
Normal file
BIN
docs/src/perf/timings-2026-06-20-verbs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
|
|
@ -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% |
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Peak resident set size (RSS) for representative workloads:
|
||||
|
||||
| Workload | Before | After | Change |
|
||||
|
|
|
|||
|
|
@ -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% |
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Peak resident set size (RSS) for representative workloads:
|
||||
|
||||
| Workload | Before | After | Change |
|
||||
|
|
|
|||
78
scripts/perf/README.md
Normal file
78
scripts/perf/README.md
Normal 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
30
scripts/perf/plot-timings.sh
Executable 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
22
scripts/perf/run-perf.sh
Executable 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"
|
||||
|
|
@ -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"],
|
||||
|
|
|
|||
36
scripts/perf/timings-2026-06-20.dat
Normal file
36
scripts/perf/timings-2026-06-20.dat
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue