From f60314daaf59d3705f08f31b7220b938ea6dd24e Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sun, 22 Feb 2026 17:04:35 -0500 Subject: [PATCH] Update performance docs (#1991) * Organize perf-stats runs * reorg * scripts/perf/timings-2026-02-22.txt * iterating * iterating * more * .gitignore * more * link checks --- .gitignore | 2 + README-dev.md | 8 +- README-profiling.md | 21 ++-- docs/src/new-in-miller-6.md | 94 +----------------- docs/src/new-in-miller-6.md.in | 94 +----------------- docs/src/perf/2026-02-22-cats.png | Bin 0 -> 47856 bytes docs/src/perf/2026-02-22-chains.png | Bin 0 -> 37994 bytes docs/src/perf/2026-02-22-verbs.png | Bin 0 -> 43735 bytes docs/src/performance.md | 35 ++++++- docs/src/performance.md.in | 35 ++++++- pkg/dsl/cst/README.md | 2 +- pkg/parsing/README.md | 2 +- pkg/terminals/repl/README.md | 3 +- pkg/types/README.md | 8 +- scripts/c2m | 6 -- scripts/chain-cmps.sh | 28 ------ scripts/chain-lengths.sh | 71 ------------- scripts/compiler-versions-time | 9 -- .../new-timings.sh | 9 -- scripts/make-big-files | 23 ----- scripts/{ => perf}/chain-1.mlr | 0 scripts/{ => perf}/compiler-versions-build | 0 scripts/{ => perf}/compiler-versions-install | 0 scripts/perf/compiler-versions-time | 9 ++ .../Makefile.no-autoconfig | 0 .../early-multi-language-timings/catc.c | 0 .../early-multi-language-timings/catc.c.txt | 0 .../early-multi-language-timings/catc0.c | 0 .../early-multi-language-timings/catc0.c.txt | 0 .../early-multi-language-timings/catd.d | 0 .../early-multi-language-timings/catd.d.txt | 0 .../early-multi-language-timings/catgo.go | 0 .../early-multi-language-timings/catgo.go.txt | 0 .../early-multi-language-timings/catgo2.go | 0 .../catgo2.go.txt | 0 .../early-multi-language-timings/catm.c | 0 .../early-multi-language-timings/catm2.c | 0 .../early-multi-language-timings/catnim.nim | 0 .../early-multi-language-timings/catrust.rs | 0 .../catrust.rs.txt | 0 .../early-multi-language-timings/catrust2.rs | 0 .../early-multi-language-timings/cutd.d | 0 .../early-multi-language-timings/cutd.d.txt | 0 .../early-multi-language-timings/cutgo.go | 0 .../early-multi-language-timings/cutgo.go.txt | 0 .../early-multi-language-timings/cutnim.nim | 0 .../do-timings.rb | 0 .../early-multi-language-timings/ff1.rs | 2 +- .../early-multi-language-timings/ff2.rs | 2 +- .../early-multi-language-timings/ff3.rs | 2 +- .../early-multi-language-timings/ff4.rs | 2 +- .../early-multi-language-timings/mand/mand.c | 0 .../mand/mand.mlr | 0 .../early-multi-language-timings/mand/mand.py | 0 .../early-multi-language-timings/mand/mand.rb | 0 .../mand/mandg.go | 0 .../mand/timings.txt | 0 .../early-multi-language-timings/mkplots.sh | 0 .../new-timings.sh | 9 ++ .../new-timings.txt | 4 +- .../nimcat.nim.txt | 0 .../nimcut.nim.txt | 0 .../early-multi-language-timings/nimlc.nim | 0 .../early-multi-language-timings/nimwc.nim | 0 .../early-multi-language-timings/t1s.rb | 0 .../early-multi-language-timings/timings.txt | 0 .../early-multi-language-timings/tn.rb | 0 scripts/{ => perf}/make-data-stream | 3 +- scripts/perf/prep-perf-data.sh | 33 ++++++ scripts/perf/time-verbs.py | 77 ++++++++++++++ scripts/perf/timings-2026-02-22.dat | 85 ++++++++++++++++ scripts/perf/timings-2026-02-22.sh | 16 +++ scripts/time-big-file | 18 ---- scripts/time-big-files | 20 ---- 74 files changed, 326 insertions(+), 406 deletions(-) create mode 100644 docs/src/perf/2026-02-22-cats.png create mode 100644 docs/src/perf/2026-02-22-chains.png create mode 100644 docs/src/perf/2026-02-22-verbs.png delete mode 100755 scripts/c2m delete mode 100755 scripts/chain-cmps.sh delete mode 100755 scripts/chain-lengths.sh delete mode 100755 scripts/compiler-versions-time delete mode 100644 scripts/early-multi-language-timings/new-timings.sh delete mode 100755 scripts/make-big-files rename scripts/{ => perf}/chain-1.mlr (100%) rename scripts/{ => perf}/compiler-versions-build (100%) rename scripts/{ => perf}/compiler-versions-install (100%) create mode 100755 scripts/perf/compiler-versions-time rename scripts/{ => perf}/early-multi-language-timings/Makefile.no-autoconfig (100%) rename scripts/{ => perf}/early-multi-language-timings/catc.c (100%) rename scripts/{ => perf}/early-multi-language-timings/catc.c.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catc0.c (100%) rename scripts/{ => perf}/early-multi-language-timings/catc0.c.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catd.d (100%) rename scripts/{ => perf}/early-multi-language-timings/catd.d.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catgo.go (100%) rename scripts/{ => perf}/early-multi-language-timings/catgo.go.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catgo2.go (100%) rename scripts/{ => perf}/early-multi-language-timings/catgo2.go.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catm.c (100%) rename scripts/{ => perf}/early-multi-language-timings/catm2.c (100%) rename scripts/{ => perf}/early-multi-language-timings/catnim.nim (100%) rename scripts/{ => perf}/early-multi-language-timings/catrust.rs (100%) rename scripts/{ => perf}/early-multi-language-timings/catrust.rs.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/catrust2.rs (100%) rename scripts/{ => perf}/early-multi-language-timings/cutd.d (100%) rename scripts/{ => perf}/early-multi-language-timings/cutd.d.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/cutgo.go (100%) rename scripts/{ => perf}/early-multi-language-timings/cutgo.go.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/cutnim.nim (100%) rename scripts/{ => perf}/early-multi-language-timings/do-timings.rb (100%) rename scripts/{ => perf}/early-multi-language-timings/ff1.rs (89%) rename scripts/{ => perf}/early-multi-language-timings/ff2.rs (90%) rename scripts/{ => perf}/early-multi-language-timings/ff3.rs (88%) rename scripts/{ => perf}/early-multi-language-timings/ff4.rs (89%) rename scripts/{ => perf}/early-multi-language-timings/mand/mand.c (100%) rename scripts/{ => perf}/early-multi-language-timings/mand/mand.mlr (100%) rename scripts/{ => perf}/early-multi-language-timings/mand/mand.py (100%) rename scripts/{ => perf}/early-multi-language-timings/mand/mand.rb (100%) rename scripts/{ => perf}/early-multi-language-timings/mand/mandg.go (100%) rename scripts/{ => perf}/early-multi-language-timings/mand/timings.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/mkplots.sh (100%) create mode 100644 scripts/perf/early-multi-language-timings/new-timings.sh rename scripts/{ => perf}/early-multi-language-timings/new-timings.txt (86%) rename scripts/{ => perf}/early-multi-language-timings/nimcat.nim.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/nimcut.nim.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/nimlc.nim (100%) rename scripts/{ => perf}/early-multi-language-timings/nimwc.nim (100%) rename scripts/{ => perf}/early-multi-language-timings/t1s.rb (100%) rename scripts/{ => perf}/early-multi-language-timings/timings.txt (100%) rename scripts/{ => perf}/early-multi-language-timings/tn.rb (100%) rename scripts/{ => perf}/make-data-stream (98%) create mode 100755 scripts/perf/prep-perf-data.sh create mode 100755 scripts/perf/time-verbs.py create mode 100644 scripts/perf/timings-2026-02-22.dat create mode 100644 scripts/perf/timings-2026-02-22.sh delete mode 100755 scripts/time-big-file delete mode 100755 scripts/time-big-files diff --git a/.gitignore b/.gitignore index c6985b12e..f2ef8ce28 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ data/nmc?.* docs/src/polyglot-dkvp-io/__pycache__ docs/site/ + +.cursor diff --git a/README-dev.md b/README-dev.md index 82a8e6aa0..452f55a8f 100644 --- a/README-dev.md +++ b/README-dev.md @@ -111,8 +111,8 @@ So, in broad overview, the key packages are: * [pkg/entrypoint](./pkg/entrypoint): All the usual contents of `main()` are here, for ease of testing. * [pkg/platform](./pkg/platform): Platform-dependent code, which as of early 2021 is the command-line parser. Handling single quotes and double quotes is different on Windows unless particular care is taken, which is what this package does. * [pkg/lib](./pkg/lib): - * Implementation of the [`Mlrval`](./pkg/types/mlrval.go) datatype which includes string/int/float/boolean/void/absent/error types. These are used for record values, as well as expression/variable values in the Miller `put`/`filter` DSL. See also below for more details. - * [`Mlrmap`](./pkg/types/mlrmap.go) is the sequence of key-value pairs which represents a Miller record. The key-lookup mechanism is optimized for Miller read/write usage patterns -- please see [mlrmap.go](./pkg/types/mlrmap.go) for more details. + * Implementation of the [`Mlrval`](./pkg/mlrval/) datatype which includes string/int/float/boolean/void/absent/error types. These are used for record values, as well as expression/variable values in the Miller `put`/`filter` DSL. See also below for more details. + * [`Mlrmap`](./pkg/mlrval/mlrmap.go) is the sequence of key-value pairs which represents a Miller record. The key-lookup mechanism is optimized for Miller read/write usage patterns -- please see [mlrmap.go](./pkg/mlrval/mlrmap.go) for more details. * [`context`](./pkg/types/context.go) supports AWK-like variables such as `FILENAME`, `NF`, `NR`, and so on. * [pkg/cli](./pkg/cli) is the flag-parsing logic for supporting Miller's command-line interface. When you type something like `mlr --icsv --ojson put '$sum = $a + $b' then filter '$sum > 1000' myfile.csv`, it's the CLI parser which makes it possible for Miller to construct a CSV record-reader, a transformer-chain of `put` then `filter`, and a JSON record-writer. * [pkg/climain](./pkg/climain) contains a layer which invokes `pkg/cli`, which was split out to avoid a Go package-import cycle. @@ -154,7 +154,7 @@ nil through the reader/transformer/writer sequence. ## More about mlrvals -[`Mlrval`](./pkg/types/mlrval.go) is the datatype of record values, as well as expression/variable values in the Miller `put`/`filter` DSL. It includes string/int/float/boolean/void/absent/error types, not unlike PHP's `zval`. +[`Mlrval`](./pkg/mlrval/) is the datatype of record values, as well as expression/variable values in the Miller `put`/`filter` DSL. It includes string/int/float/boolean/void/absent/error types, not unlike PHP's `zval`. * Miller's `absent` type is like Javascript's `undefined` -- it's for times when there is no such key, as in a DSL expression `$out = $foo` when the input record is `$x=3,y=4` -- there is no `$foo` so `$foo` has `absent` type. Nothing is written to the `$out` field in this case. See also [here](https://miller.readthedocs.io/en/latest/reference-main-null-data) for more information. * Miller's `void` type is like Javascript's `null` -- it's for times when there is a key with no value, as in `$out = $x` when the input record is `$x=,$y=4`. This is an overlap with `string` type, since a void value looks like an empty string. I've gone back and forth on this (including when I was writing the C implementation) -- whether to retain `void` as a distinct type from empty-string, or not. I ended up keeping it as it made the `Mlrval` logic easier to understand. @@ -162,7 +162,7 @@ nil through the reader/transformer/writer sequence. * Miller's number handling makes auto-overflow from int to float transparent, while preserving the possibility of 64-bit bitwise arithmetic. * This is different from JavaScript, which has only double-precision floats and thus no support for 64-bit numbers (note however that there is now [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)). * This is also different from C and Go, wherein casts are necessary -- without which int arithmetic overflows. - * See also [here](https://miller.readthedocs.io/en/latest/reference-main-arithmetic) for the semantics of Miller arithmetic, which the [`Mlrval`](./pkg/types/mlrval.go) class implements. + * See also [here](https://miller.readthedocs.io/en/latest/reference-main-arithmetic) for the semantics of Miller arithmetic, which the [`Mlrval`](./pkg/mlrval/) package implements. ## Performance optimizations diff --git a/README-profiling.md b/README-profiling.md index 5c067614e..8279ded8b 100644 --- a/README-profiling.md +++ b/README-profiling.md @@ -9,7 +9,7 @@ Run the profiler: ``` -mlr --cpuprofile cpu.pprof --csv put -f scripts/chain-1.mlr ~/tmp/big.csv > /dev/null +mlr --cpuprofile cpu.pprof --csv put -f scripts/perf/chain-1.mlr ~/data/big.csv > /dev/null ``` (or whatever command-line flags for Miller). @@ -39,13 +39,12 @@ Note that you can drill into subcomponents of the flame graph: Scripts: -* [./scripts/make-big-files](./scripts/make-big-files) -- Create million-record data files in various formats. -* [./scripts/chain-cmps.sh](./scripts/chain-cmps.sh) -- Run a few processing scenarios on the million-record CSV file. - * [./scripts/chain-1.mlr](./scripts/chain-1.mlr) -- An example `mlr put` used by the previous script -* [./scripts/time-big-files](./scripts/time-big-files) -- Runs `mlr cat` for million-record files of various file formats. Catting files isn't intrinsically interesting but it shows how input and output processing vary over file formats. - * [./scripts/time-big-file](./scripts/time-big-file) -- Helper script for the former. -* [./scripts/chain-lengths.sh](./scripts/chain-lengths.sh) -- Run longer and longer chains of `scripts/chain1.mlr`, showing how Miller handles multicore and concurrency. -* [./scripts/make-data-stream](./scripts/make-data-stream) -- Create an endless stream of data to be piped into Miller for steady-state load-testing: e.g. `scripts/make-data-stream | mlr ...` then look at `htop` in another window. +* [./scripts/perf/prep-perf-data.sh](./scripts/perf/prep-perf-data.sh) -- Create million-record data files in various formats. +* [./scripts/perf/time-verbs.py](./scripts/perf/time-verbs.py) -- Run a few processing scenarios on the million-record CSV file. + * One batch of cases times various Miller verbs. + * A second batch of cases runs `mlr cat` for million-record files of various file formats. Catting files isn't intrinsically interesting but it shows how input and output processing vary over file formats. + * A third batch of cases runs longer and longer chains of `scripts/perf/chain-1.mlr`, showing how Miller handles multicore and concurrency. +* [./scripts/perf/make-data-stream](./scripts/perf/make-data-stream) -- Create an endless stream of data to be piped into Miller for steady-state load-testing: e.g. `scripts/perf/make-data-stream | mlr ...` then look at `htop` in another window. Notes: @@ -55,9 +54,9 @@ Notes: # How to vary compiler versions -* [./scripts/compiler-versions-install](./scripts/compiler-versions-install) -* [./scripts/compiler-versions-build](./scripts/compiler-versions-build) -* [./scripts/compiler-versions-time](./scripts/compiler-versions-time) +* [./scripts/perf/compiler-versions-install](./scripts/compiler-versions-install) +* [./scripts/perf/compiler-versions-build](./scripts/compiler-versions-build) +* [./scripts/perf/compiler-versions-time](./scripts/compiler-versions-time) # How to control garbage collection diff --git a/docs/src/new-in-miller-6.md b/docs/src/new-in-miller-6.md index 86a52a40d..93698d0a4 100644 --- a/docs/src/new-in-miller-6.md +++ b/docs/src/new-in-miller-6.md @@ -306,96 +306,4 @@ Please see the [section on emit statements](reference-dsl-output-statements.md#e ## Performance benchmarks -For performance testing, the [example.csv](https://github.com/johnkerl/miller/blob/main/docs/src/example.csv) file -[was expanded](https://github.com/johnkerl/miller/blob/main/scripts/make-big-files) into a million-line CSV file, -then converted to DKVP, JSON, etc. - -Notes: - -* These benchmarks were run on two laptops: a commodity Mac laptop with four CPUs, on MacOS Monterey, using `go1.16.5 darwin/amd64`, and a commodity Linux Lenovo with eight CPUs, on Ubuntu 21.10, using `go1.17.5 linux/amd64`. -* Interestingly, I noted a significant slowdown -- for this particular Linux laptop on low battery -- for the Go version but not the C version. Perhaps multicore interacts with power-saving mode. -* As of late 2021, Miller has been benchmarked using Go compiler versions 1.15.15, 1.16.12, 1.17.5, and 1.18beta1, with no significant performance changes attributable to compiler versions. - -For the [first benchmark](https://github.com/johnkerl/miller/blob/main/scripts/chain-cmps.sh), the format is CSV and the operations are varied: - -**Mac** - -| Operation | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV check | 1.541 | 1.216 | 1.27x | -| CSV cat | 2.403 | 1.430 | 1.68x | -| CSV tail | 1.526 | 1.222 | 1.25x | -| CSV tac | 2.785 | 3.122 | 0.89x | -| CSV sort -f shape | 2.996 | 3.139 | 0.95x | -| CSV sort -n quantity | 4.895 | 5.200 | 0.94x | -| CSV stats1 | 2.955 | 1.865 | 1.58x | -| CSV put expressions | 5.642 | 2.577 | 2.19x | - -**Linux** - -| Operation | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV check | 0.680 | 1.104 | 0.62x | -| CSV cat | 1.066 | 1.231 | 0.87x | -| CSV tail | 0.691 | 1.130 | 0.61x | -| CSV tac | 1.648 | 2.620 | 0.63x | -| CSV sort -f shape | 2.087 | 2.953 | 0.71x | -| CSV sort -n quantity | 5.588 | 5.337 | 1.05x | -| CSV stats1 | 2.376 | 1.751 | 1.36x | -| CSV put expressions | 4.520 | 2.091 | 2.16x | - -For the [second benchmark](https://github.com/johnkerl/miller/blob/main/scripts/time-big-files), we have `mlr cat` of those files, varying file types, with processing times shown. Catting out files as-is isn't a particularly useful operation in itself, but it gives an idea of how processing time depends on file format: - -**Mac** - -| Format | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV | 2.393 | 1.493 | 1.60x | -| CSV-lite | 1.644 | 1.351 | 1.22x | -| DKVP | 2.418 | 1.920 | 1.26x | -| NIDX | 1.053 | 0.958 | 1.10x | -| XTAB | 4.978 | 2.003 | 2.49x | -| JSON | 10.966 | 10.569 | 1.04x | - -**Linux** - -| Format | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV | 1.069 | 1.157 | 0.92x | -| CSV-lite | 0.640 | 1.187 | 0.54x | -| DKVP | 1.017 | 1.853 | 0.55x | -| NIDX | 0.623 | 1.398 | 0.45x | -| XTAB | 2.159 | 1.893 | 1.14x | -| JSON | 5.077 | 10.445 | 0.49x | - -For the [third benchmark](https://github.com/johnkerl/miller/blob/main/scripts/chain-lengths.sh), we have longer and longer then-chains: `mlr put ...`, then `mlr put ... then put ...`, etc. -- deepening the then-chain from one to six: - -**Mac** - -| Chain length | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| 1 | 5.709 | 2.567 | 2.22x | -| 2 | 8.926 | 3.110 | 2.87x | -| 3 | 11.915 | 3.712 | 3.21x | -| 4 | 15.093 | 4.391 | 3.44x | -| 5 | 18.209 | 5.090 | 3.58x | -| 6 | 21.109 | 6.032 | 3.50x | - -**Linux** - -| Chain length | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| 1 | 4.732 | 2.106 | 2.25x | -| 2 | 8.103 | 2.992 | 2.71x | -| 3 | 11.42 | 3.4743 | 3.29x | -| 4 | 14.904 | 3.859 | 3.86x | -| 5 | 18.128 | 4.1563 | 4.36x | -| 6 | 21.827 | 4.512 | 4.84x | - -Notes: - -* CSV processing is particularly improved in Miller 6. -* Record I/O is improved across the board, except that JSON continues to be a CPU-intensive format. Miller 6 JSON throughput is the same on Mac and Linux; Miller 5 did better than Miller 6 but only on Linux, not Mac. -* Miller 6's `sort` merits more performance analysis. -* Even single-verb processing with `put` and `stats1` is significantly faster on both platforms. -* Longer then-chains benefit even more from Miller 6's [multicore approach](cpu.md). +See the [performance page](performance.md). diff --git a/docs/src/new-in-miller-6.md.in b/docs/src/new-in-miller-6.md.in index 2da9d3feb..9a3dca63c 100644 --- a/docs/src/new-in-miller-6.md.in +++ b/docs/src/new-in-miller-6.md.in @@ -255,96 +255,4 @@ Please see the [section on emit statements](reference-dsl-output-statements.md#e ## Performance benchmarks -For performance testing, the [example.csv](https://github.com/johnkerl/miller/blob/main/docs/src/example.csv) file -[was expanded](https://github.com/johnkerl/miller/blob/main/scripts/make-big-files) into a million-line CSV file, -then converted to DKVP, JSON, etc. - -Notes: - -* These benchmarks were run on two laptops: a commodity Mac laptop with four CPUs, on MacOS Monterey, using `go1.16.5 darwin/amd64`, and a commodity Linux Lenovo with eight CPUs, on Ubuntu 21.10, using `go1.17.5 linux/amd64`. -* Interestingly, I noted a significant slowdown -- for this particular Linux laptop on low battery -- for the Go version but not the C version. Perhaps multicore interacts with power-saving mode. -* As of late 2021, Miller has been benchmarked using Go compiler versions 1.15.15, 1.16.12, 1.17.5, and 1.18beta1, with no significant performance changes attributable to compiler versions. - -For the [first benchmark](https://github.com/johnkerl/miller/blob/main/scripts/chain-cmps.sh), the format is CSV and the operations are varied: - -**Mac** - -| Operation | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV check | 1.541 | 1.216 | 1.27x | -| CSV cat | 2.403 | 1.430 | 1.68x | -| CSV tail | 1.526 | 1.222 | 1.25x | -| CSV tac | 2.785 | 3.122 | 0.89x | -| CSV sort -f shape | 2.996 | 3.139 | 0.95x | -| CSV sort -n quantity | 4.895 | 5.200 | 0.94x | -| CSV stats1 | 2.955 | 1.865 | 1.58x | -| CSV put expressions | 5.642 | 2.577 | 2.19x | - -**Linux** - -| Operation | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV check | 0.680 | 1.104 | 0.62x | -| CSV cat | 1.066 | 1.231 | 0.87x | -| CSV tail | 0.691 | 1.130 | 0.61x | -| CSV tac | 1.648 | 2.620 | 0.63x | -| CSV sort -f shape | 2.087 | 2.953 | 0.71x | -| CSV sort -n quantity | 5.588 | 5.337 | 1.05x | -| CSV stats1 | 2.376 | 1.751 | 1.36x | -| CSV put expressions | 4.520 | 2.091 | 2.16x | - -For the [second benchmark](https://github.com/johnkerl/miller/blob/main/scripts/time-big-files), we have `mlr cat` of those files, varying file types, with processing times shown. Catting out files as-is isn't a particularly useful operation in itself, but it gives an idea of how processing time depends on file format: - -**Mac** - -| Format | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV | 2.393 | 1.493 | 1.60x | -| CSV-lite | 1.644 | 1.351 | 1.22x | -| DKVP | 2.418 | 1.920 | 1.26x | -| NIDX | 1.053 | 0.958 | 1.10x | -| XTAB | 4.978 | 2.003 | 2.49x | -| JSON | 10.966 | 10.569 | 1.04x | - -**Linux** - -| Format | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| CSV | 1.069 | 1.157 | 0.92x | -| CSV-lite | 0.640 | 1.187 | 0.54x | -| DKVP | 1.017 | 1.853 | 0.55x | -| NIDX | 0.623 | 1.398 | 0.45x | -| XTAB | 2.159 | 1.893 | 1.14x | -| JSON | 5.077 | 10.445 | 0.49x | - -For the [third benchmark](https://github.com/johnkerl/miller/blob/main/scripts/chain-lengths.sh), we have longer and longer then-chains: `mlr put ...`, then `mlr put ... then put ...`, etc. -- deepening the then-chain from one to six: - -**Mac** - -| Chain length | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| 1 | 5.709 | 2.567 | 2.22x | -| 2 | 8.926 | 3.110 | 2.87x | -| 3 | 11.915 | 3.712 | 3.21x | -| 4 | 15.093 | 4.391 | 3.44x | -| 5 | 18.209 | 5.090 | 3.58x | -| 6 | 21.109 | 6.032 | 3.50x | - -**Linux** - -| Chain length | Miller 5 | Miller 6 | Speedup | -| --- | --- | --- | --- | -| 1 | 4.732 | 2.106 | 2.25x | -| 2 | 8.103 | 2.992 | 2.71x | -| 3 | 11.42 | 3.4743 | 3.29x | -| 4 | 14.904 | 3.859 | 3.86x | -| 5 | 18.128 | 4.1563 | 4.36x | -| 6 | 21.827 | 4.512 | 4.84x | - -Notes: - -* CSV processing is particularly improved in Miller 6. -* Record I/O is improved across the board, except that JSON continues to be a CPU-intensive format. Miller 6 JSON throughput is the same on Mac and Linux; Miller 5 did better than Miller 6 but only on Linux, not Mac. -* Miller 6's `sort` merits more performance analysis. -* Even single-verb processing with `put` and `stats1` is significantly faster on both platforms. -* Longer then-chains benefit even more from Miller 6's [multicore approach](cpu.md). +See the [performance page](performance.md). diff --git a/docs/src/perf/2026-02-22-cats.png b/docs/src/perf/2026-02-22-cats.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ca40b79800ac8741d6ee2c0688c7d32b65388c GIT binary patch literal 47856 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 hOaK3$I}$j1LK)Vdz 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

{s9 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 literal 0 HcmV?d00001 diff --git a/docs/src/performance.md b/docs/src/performance.md index 0449a6fbc..ed7e00b0b 100644 --- a/docs/src/performance.md +++ b/docs/src/performance.md @@ -16,8 +16,6 @@ Quick links: # Performance -See also the [performance-benchmarks section](new-in-miller-6.md#performance-benchmarks). - ## Disclaimer In a previous version of this page, I compared Miller to some items in the Unix toolkit in terms of run time. But such comparisons are very much not apples-to-apples: @@ -34,7 +32,38 @@ In a previous version of this page, I compared Miller to some items in the Unix Miller can do many kinds of processing on key-value-pair data using elapsed time roughly of the same order of magnitude as items in the Unix toolkit can handle positionally indexed data. Specific results vary widely by platform, implementation details, and multi-core use (or not). Lastly, specific special-purpose non-record-aware processing will run far faster if implemented in `grep`, `sed`, etc. -## Some examples +## Performance benchmarks + +For performance testing, the [example.csv](https://github.com/johnkerl/miller/blob/main/docs/src/example.csv) file +[was expanded](https://github.com/johnkerl/miller/blob/main/scripts/perf/prep-perf-data.sh) into a million-line CSV file, +then converted to DKVP, JSON, etc. + +Notes: + +* These benchmarks were run in early 2026 on MacBook Air laptop with an M1 processor. +* As of late 2021, Miller was benchmarked using Go compiler versions 1.15.15, 1.16.12, 1.17.5, and 1.18beta1, with no significant performance changes attributable to compiler versions. + +For the [first benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), the format is CSV and the operations were varied: + +![perf/2026-02-22-verbs.png](perf/2026-02-22-verbs.png) + +For the [second benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), we have `mlr cat` of those files, varying file types, with processing times shown. Catting out files as-is isn't a particularly useful operation in itself, but it gives an idea of how processing time depends on file format: + +![perf/2026-02-22-cats.png](perf/2026-02-22-cats.png) + +For the [third benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), we have longer and longer then-chains: `mlr put ...`, then `mlr put ... then put ...`, etc. -- deepening the then-chain from one to four: + +![perf/2026-02-22-chains.png](perf/2026-02-22-chains.png) + +Notes: + +* CSV processing was particularly improved in Miller 6. +* Record I/O was improved across the board, except that JSON continues to be a CPU-intensive format. Miller 6 JSON throughput was the same on Mac and Linux; Miller 5 did better than Miller 6 but only on Linux, not Mac. +* Miller 6.0.0's initial issues with `sort` and JSON processing have been resolved. +* Even single-verb processing with `put` and `stats1` was significantly faster on both platforms. +* Longer then-chains benefit even more from Miller 6's [multicore approach](cpu.md). + +## Decompression options This is some data from [https://community.opencellid.org](https://community.opencellid.org): approximately 40 million records, 1.2GB compressed, 2.9GB uncompressed: diff --git a/docs/src/performance.md.in b/docs/src/performance.md.in index edc2fa143..aa4c7e99d 100644 --- a/docs/src/performance.md.in +++ b/docs/src/performance.md.in @@ -1,7 +1,5 @@ # Performance -See also the [performance-benchmarks section](new-in-miller-6.md#performance-benchmarks). - ## Disclaimer In a previous version of this page, I compared Miller to some items in the Unix toolkit in terms of run time. But such comparisons are very much not apples-to-apples: @@ -18,7 +16,38 @@ In a previous version of this page, I compared Miller to some items in the Unix Miller can do many kinds of processing on key-value-pair data using elapsed time roughly of the same order of magnitude as items in the Unix toolkit can handle positionally indexed data. Specific results vary widely by platform, implementation details, and multi-core use (or not). Lastly, specific special-purpose non-record-aware processing will run far faster if implemented in `grep`, `sed`, etc. -## Some examples +## Performance benchmarks + +For performance testing, the [example.csv](https://github.com/johnkerl/miller/blob/main/docs/src/example.csv) file +[was expanded](https://github.com/johnkerl/miller/blob/main/scripts/perf/prep-perf-data.sh) into a million-line CSV file, +then converted to DKVP, JSON, etc. + +Notes: + +* These benchmarks were run in early 2026 on MacBook Air laptop with an M1 processor. +* As of late 2021, Miller was benchmarked using Go compiler versions 1.15.15, 1.16.12, 1.17.5, and 1.18beta1, with no significant performance changes attributable to compiler versions. + +For the [first benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), the format is CSV and the operations were varied: + +![perf/2026-02-22-verbs.png](perf/2026-02-22-verbs.png) + +For the [second benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), we have `mlr cat` of those files, varying file types, with processing times shown. Catting out files as-is isn't a particularly useful operation in itself, but it gives an idea of how processing time depends on file format: + +![perf/2026-02-22-cats.png](perf/2026-02-22-cats.png) + +For the [third benchmark](https://github.com/johnkerl/miller/blob/main/scripts/perf/time-verbs.py), we have longer and longer then-chains: `mlr put ...`, then `mlr put ... then put ...`, etc. -- deepening the then-chain from one to four: + +![perf/2026-02-22-chains.png](perf/2026-02-22-chains.png) + +Notes: + +* CSV processing was particularly improved in Miller 6. +* Record I/O was improved across the board, except that JSON continues to be a CPU-intensive format. Miller 6 JSON throughput was the same on Mac and Linux; Miller 5 did better than Miller 6 but only on Linux, not Mac. +* Miller 6.0.0's initial issues with `sort` and JSON processing have been resolved. +* Even single-verb processing with `put` and `stats1` was significantly faster on both platforms. +* Longer then-chains benefit even more from Miller 6's [multicore approach](cpu.md). + +## Decompression options This is some data from [https://community.opencellid.org](https://community.opencellid.org): approximately 40 million records, 1.2GB compressed, 2.9GB uncompressed: diff --git a/pkg/dsl/cst/README.md b/pkg/dsl/cst/README.md index d1936faf9..08f815a1b 100644 --- a/pkg/dsl/cst/README.md +++ b/pkg/dsl/cst/README.md @@ -11,7 +11,7 @@ See [../dsl/README.md](../README.md) for more information about Miller's use of Go is a strongly typed language, but the AST is polymorphic. This results in if/else or switch statements as an AST is walked. -Also, when we modify code, there can be changes in the [BNF grammar](../../parsing/mlr.bnf) not yet reflected in the [AST](../../pkg/dsl/ast_types.go). Likewise, there can be AST changes not yet reflected here. (Example: you are partway through adding a new binary operator to the grammar.) +Also, when we modify code, there can be changes in the [BNF grammar](../../parsing/mlr.bnf) not yet reflected in the [AST](../ast_types.go). Likewise, there can be AST changes not yet reflected here. (Example: you are partway through adding a new binary operator to the grammar.) As a result, throughout the code, there are error checks which may seem redundant but which are in place to make incremental development more pleasant and robust. diff --git a/pkg/parsing/README.md b/pkg/parsing/README.md index 161e5c75d..bec012621 100644 --- a/pkg/parsing/README.md +++ b/pkg/parsing/README.md @@ -23,4 +23,4 @@ tools/build-dsl Making changes to `mlr.bnf` requires several minutes to re-run GOCC. For experimental changes, please see the -[experiments](../../../experiments/dsl-parser) directory. +[cmd/experiments/dsl_parser](../../../cmd/experiments/dsl_parser) directory. diff --git a/pkg/terminals/repl/README.md b/pkg/terminals/repl/README.md index 5fca6d415..1777a7767 100644 --- a/pkg/terminals/repl/README.md +++ b/pkg/terminals/repl/README.md @@ -106,6 +106,5 @@ One subtlety is that non-assignment expressions like `NR < 10` are filter statem * [entry.go](./entry.go) -- shell command-line entry point to the Miller repl command line. E.g. handles `mlr repl --json` which is typed at the shell prompt, and starts a command-line session at the Miller REPL prompt. * [session.go](./session.go) -- constructs a `Repl` object and ingests command lines, dispatching them either to the DSL (e.g. `$z = $x + $y`) or to the non-DSL verb handler (e.g. `:open foo.dat` or `help`). * [prompt.go](./prompt.go) -- Handling for default and customized banners/prompts for the Miller REPL. -* [dsl.go](./dsl.go) -- Handler for taking DSL statements typed in interactively by the user, parsing them to an AST, building a CST from the AST, and executing the CST. -* [ast.go](./ast.go) -- Interface between the REPL and the DSL-to-AST parser. +* [dsl.go](./dsl.go) -- Handler for taking DSL statements typed in interactively by the user, parsing them to an AST (via the [parsing](../../parsing/) package), building a CST from the AST, and executing the CST. * [verbs.go](./verbs.go) -- Handlers for non-DSL statements like `:open foo.dat` or `:help`. diff --git a/pkg/types/README.md b/pkg/types/README.md index 42eda57eb..1e9613a40 100644 --- a/pkg/types/README.md +++ b/pkg/types/README.md @@ -1,8 +1,8 @@ -This contains the implementation of the [`types.Mlrval`](./mlrval.go) datatype which is used for record values, as well as expression/variable values in the Miller `put`/`filter` DSL. +This package contains [`types.Context`](./context.go) and related stream types. The [`Mlrval`](../mlrval/) and [`Mlrmap`](../mlrval/mlrmap.go) types used for record values and expression/variable values in the Miller `put`/`filter` DSL are implemented in the [pkg/mlrval](../mlrval/) package. ## Mlrval -The [`types.Mlrval`](./mlrval.go) structure includes **string, int, float, boolean, array-of-mlrval, map-string-to-mlrval, void, absent, and error** types as well as type-conversion logic for various operators. +The [`Mlrval`](../mlrval/) structure (in package `mlrval`) includes **string, int, float, boolean, array-of-mlrval, map-string-to-mlrval, void, absent, and error** types as well as type-conversion logic for various operators. * Miller's `absent` type is like Javascript's `undefined` -- it's for times when there is no such key, as in a DSL expression `$out = $foo` when the input record is `$x=3,y=4` -- there is no `$foo` so `$foo` has `absent` type. Nothing is written to the `$out` field in this case. See also [here](https://miller.readthedocs.io/en/latest/reference-main-null-data) for more information. * Miller's `void` type is like Javascript's `null` -- it's for times when there is a key with no value, as in `$out = $x` when the input record is `$x=,$y=4`. This is an overlap with `string` type, since a void value looks like an empty string. I've gone back and forth on this (including when I was writing the C implementation) -- whether to retain `void` as a distinct type from empty-string, or not. I ended up keeping it as it made the `Mlrval` logic easier to understand. @@ -20,7 +20,7 @@ The [`types.Mlrval`](./mlrval.go) structure includes **string, int, float, boole # Mlrmap -[`types.Mlrmap`](./mlrmap.go) is the sequence of key-value pairs which represents a Miller record. The key-lookup mechanism is optimized for Miller read/write usage patterns -- please see `mlrmap.go` for more details. +[`Mlrmap`](../mlrval/mlrmap.go) is the sequence of key-value pairs which represents a Miller record (implemented in package `mlrval`). The key-lookup mechanism is optimized for Miller read/write usage patterns -- please see [mlrmap.go](../mlrval/mlrmap.go) for more details. It's also an ordered map structure, with string keys and Mlrval values. This is used within Mlrval itself. @@ -31,7 +31,7 @@ It's also an ordered map structure, with string keys and Mlrval values. This is # A note on JSON * The code for JSON I/O is mixed between `Mlrval` and `Mlrmap. This is unsurprising since JSON is a mutually recursive data structure -- arrays can contain maps and vice versa. -* JSON has non-collection types (string, int, float, etc) as well as collection types (array and object). Support for objects is principally in [./mlrmap_json.go](mlrmap_json.go); support for non-collection types as well as arrays is in [./mlrval_json.go](mlrval_json.go). +* JSON has non-collection types (string, int, float, etc) as well as collection types (array and object). Support for objects is principally in [mlrmap_json.go](../mlrval/mlrmap_json.go); support for non-collection types as well as arrays is in [mlrval_json.go](../mlrval/mlrval_json.go). * Both multi-line and single-line formats are supported. * Callsites for JSON output are record-writing (e.g. `--ojson`), the `dump` and `print` DSL routines, and the `json_stringify` DSL function. * The choice between single-line and multi-line for JSON record-writing is controlled by `--jvstack` and `--no-jvstack`, the former (multiline) being the default. diff --git a/scripts/c2m b/scripts/c2m deleted file mode 100755 index b54c2623c..000000000 --- a/scripts/c2m +++ /dev/null @@ -1,6 +0,0 @@ -for x in "$@"; do - echo $x - sed "s:'.*':-f \${CASEDIR}/mlr:" $x/cmd > $x/cmd.tmp - sed "s:[^']*'::" $x/cmd | sed "s:'.*::" | left > $x/mlr - mv $x/cmd.tmp $x/cmd -done diff --git a/scripts/chain-cmps.sh b/scripts/chain-cmps.sh deleted file mode 100755 index 186c9d5bb..000000000 --- a/scripts/chain-cmps.sh +++ /dev/null @@ -1,28 +0,0 @@ -mlrs="mlr" -if [ $# -ge 1 ]; then - mlrs="$@" -fi - -#reps="1" -reps="1 2 3" - -echo; for mlr in $mlrs; do for k in $reps; do justtime $mlr --csv --from ~/tmp/big.csv check > /dev/null; done; done -echo; for mlr in $mlrs; do for k in $reps; do justtime $mlr --csv --from ~/tmp/big.csv cat > /dev/null; done; done -echo; for mlr in $mlrs; do for k in $reps; do justtime $mlr --csv --from ~/tmp/big.csv tail > /dev/null; done; done -echo; for mlr in $mlrs; do for k in $reps; do justtime $mlr --csv --from ~/tmp/big.csv tac > /dev/null; done; done - -echo; for mlr in $mlrs; do for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv sort -f shape > /dev/null; -done; done - -echo; for mlr in $mlrs; do for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv sort -n quantity > /dev/null; -done; done - -echo; for mlr in $mlrs; do for k in $reps; do - justtime $mlr --c2p stats1 -a min,mean,max -f quantity,rate -g shape ~/tmp/big.csv > /dev/null -done; done - -echo; for mlr in $mlrs; do for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv put -f scripts/chain-1.mlr > /dev/null -done; done diff --git a/scripts/chain-lengths.sh b/scripts/chain-lengths.sh deleted file mode 100755 index a584ed738..000000000 --- a/scripts/chain-lengths.sh +++ /dev/null @@ -1,71 +0,0 @@ -mlrs="mlr" -if [ $# -ge 1 ]; then - mlrs="$@" -fi - -#reps="1" -reps="1 2 3" -#reps="1 2 3 4 5 6 7 8 9 10" - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done - -echo; for mlr in $mlrs; do - for k in $reps; do - justtime $mlr --csv --from ~/tmp/big.csv \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - then put -f scripts/chain-1.mlr \ - > /dev/null - done -done diff --git a/scripts/compiler-versions-time b/scripts/compiler-versions-time deleted file mode 100755 index 03ed64965..000000000 --- a/scripts/compiler-versions-time +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv check ~/tmp/big.csv > /dev/null; done -echo - -for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv cat ~/tmp/big.csv > /dev/null; done -echo - -for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv --from ~/tmp/big.csv put -f ./scripts/chain-1.mlr > /dev/null; done diff --git a/scripts/early-multi-language-timings/new-timings.sh b/scripts/early-multi-language-timings/new-timings.sh deleted file mode 100644 index ec9345a07..000000000 --- a/scripts/early-multi-language-timings/new-timings.sh +++ /dev/null @@ -1,9 +0,0 @@ -justtime ./catc < ~/tmp/big > /dev/null -justtime ./catc0 < ~/tmp/big > /dev/null -justtime ./catm < ~/tmp/big > /dev/null -justtime ./catrust < ~/tmp/big > /dev/null -justtime ./catrust2 < ~/tmp/big > /dev/null -justtime ./ff1 < ~/tmp/big > /dev/null -justtime ./ff2 < ~/tmp/big > /dev/null -justtime ./ff3 < ~/tmp/big > /dev/null -justtime ./catgo < ~/tmp/big > /dev/null diff --git a/scripts/make-big-files b/scripts/make-big-files deleted file mode 100755 index e23d2fcb3..000000000 --- a/scripts/make-big-files +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -set -x - -mkdir ~/tmp/ - -mlr --csv \ - repeat -n 100000 \ - then shuffle \ - then put ' - begin{@index=1} - $k = NR; - @index += urandint(2,10); - $index=@index; - $quantity=fmtnum(urandrange(50,100),"%.4f"); - $rate=fmtnum(urandrange(1,10),"%.4f"); - ' \ -docs/src/example.csv > ~/tmp/big.csv - -mlr --c2d cat ~/tmp/big.csv > ~/tmp/big.dkvp -mlr --c2j cat ~/tmp/big.csv > ~/tmp/big.json -mlr --c2n cat ~/tmp/big.csv > ~/tmp/big.nidx -mlr --c2x cat ~/tmp/big.csv > ~/tmp/big.xtab diff --git a/scripts/chain-1.mlr b/scripts/perf/chain-1.mlr similarity index 100% rename from scripts/chain-1.mlr rename to scripts/perf/chain-1.mlr diff --git a/scripts/compiler-versions-build b/scripts/perf/compiler-versions-build similarity index 100% rename from scripts/compiler-versions-build rename to scripts/perf/compiler-versions-build diff --git a/scripts/compiler-versions-install b/scripts/perf/compiler-versions-install similarity index 100% rename from scripts/compiler-versions-install rename to scripts/perf/compiler-versions-install diff --git a/scripts/perf/compiler-versions-time b/scripts/perf/compiler-versions-time new file mode 100755 index 000000000..026fc288c --- /dev/null +++ b/scripts/perf/compiler-versions-time @@ -0,0 +1,9 @@ +#!/bin/sh + +for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv check ~/data/big.csv > /dev/null; done +echo + +for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv cat ~/data/big.csv > /dev/null; done +echo + +for mlr in mlr5 mlr-go1.1*; do justtime $mlr --csv --from ~/data/big.csv put -f ./scripts/chain-1.mlr > /dev/null; done diff --git a/scripts/early-multi-language-timings/Makefile.no-autoconfig b/scripts/perf/early-multi-language-timings/Makefile.no-autoconfig similarity index 100% rename from scripts/early-multi-language-timings/Makefile.no-autoconfig rename to scripts/perf/early-multi-language-timings/Makefile.no-autoconfig diff --git a/scripts/early-multi-language-timings/catc.c b/scripts/perf/early-multi-language-timings/catc.c similarity index 100% rename from scripts/early-multi-language-timings/catc.c rename to scripts/perf/early-multi-language-timings/catc.c diff --git a/scripts/early-multi-language-timings/catc.c.txt b/scripts/perf/early-multi-language-timings/catc.c.txt similarity index 100% rename from scripts/early-multi-language-timings/catc.c.txt rename to scripts/perf/early-multi-language-timings/catc.c.txt diff --git a/scripts/early-multi-language-timings/catc0.c b/scripts/perf/early-multi-language-timings/catc0.c similarity index 100% rename from scripts/early-multi-language-timings/catc0.c rename to scripts/perf/early-multi-language-timings/catc0.c diff --git a/scripts/early-multi-language-timings/catc0.c.txt b/scripts/perf/early-multi-language-timings/catc0.c.txt similarity index 100% rename from scripts/early-multi-language-timings/catc0.c.txt rename to scripts/perf/early-multi-language-timings/catc0.c.txt diff --git a/scripts/early-multi-language-timings/catd.d b/scripts/perf/early-multi-language-timings/catd.d similarity index 100% rename from scripts/early-multi-language-timings/catd.d rename to scripts/perf/early-multi-language-timings/catd.d diff --git a/scripts/early-multi-language-timings/catd.d.txt b/scripts/perf/early-multi-language-timings/catd.d.txt similarity index 100% rename from scripts/early-multi-language-timings/catd.d.txt rename to scripts/perf/early-multi-language-timings/catd.d.txt diff --git a/scripts/early-multi-language-timings/catgo.go b/scripts/perf/early-multi-language-timings/catgo.go similarity index 100% rename from scripts/early-multi-language-timings/catgo.go rename to scripts/perf/early-multi-language-timings/catgo.go diff --git a/scripts/early-multi-language-timings/catgo.go.txt b/scripts/perf/early-multi-language-timings/catgo.go.txt similarity index 100% rename from scripts/early-multi-language-timings/catgo.go.txt rename to scripts/perf/early-multi-language-timings/catgo.go.txt diff --git a/scripts/early-multi-language-timings/catgo2.go b/scripts/perf/early-multi-language-timings/catgo2.go similarity index 100% rename from scripts/early-multi-language-timings/catgo2.go rename to scripts/perf/early-multi-language-timings/catgo2.go diff --git a/scripts/early-multi-language-timings/catgo2.go.txt b/scripts/perf/early-multi-language-timings/catgo2.go.txt similarity index 100% rename from scripts/early-multi-language-timings/catgo2.go.txt rename to scripts/perf/early-multi-language-timings/catgo2.go.txt diff --git a/scripts/early-multi-language-timings/catm.c b/scripts/perf/early-multi-language-timings/catm.c similarity index 100% rename from scripts/early-multi-language-timings/catm.c rename to scripts/perf/early-multi-language-timings/catm.c diff --git a/scripts/early-multi-language-timings/catm2.c b/scripts/perf/early-multi-language-timings/catm2.c similarity index 100% rename from scripts/early-multi-language-timings/catm2.c rename to scripts/perf/early-multi-language-timings/catm2.c diff --git a/scripts/early-multi-language-timings/catnim.nim b/scripts/perf/early-multi-language-timings/catnim.nim similarity index 100% rename from scripts/early-multi-language-timings/catnim.nim rename to scripts/perf/early-multi-language-timings/catnim.nim diff --git a/scripts/early-multi-language-timings/catrust.rs b/scripts/perf/early-multi-language-timings/catrust.rs similarity index 100% rename from scripts/early-multi-language-timings/catrust.rs rename to scripts/perf/early-multi-language-timings/catrust.rs diff --git a/scripts/early-multi-language-timings/catrust.rs.txt b/scripts/perf/early-multi-language-timings/catrust.rs.txt similarity index 100% rename from scripts/early-multi-language-timings/catrust.rs.txt rename to scripts/perf/early-multi-language-timings/catrust.rs.txt diff --git a/scripts/early-multi-language-timings/catrust2.rs b/scripts/perf/early-multi-language-timings/catrust2.rs similarity index 100% rename from scripts/early-multi-language-timings/catrust2.rs rename to scripts/perf/early-multi-language-timings/catrust2.rs diff --git a/scripts/early-multi-language-timings/cutd.d b/scripts/perf/early-multi-language-timings/cutd.d similarity index 100% rename from scripts/early-multi-language-timings/cutd.d rename to scripts/perf/early-multi-language-timings/cutd.d diff --git a/scripts/early-multi-language-timings/cutd.d.txt b/scripts/perf/early-multi-language-timings/cutd.d.txt similarity index 100% rename from scripts/early-multi-language-timings/cutd.d.txt rename to scripts/perf/early-multi-language-timings/cutd.d.txt diff --git a/scripts/early-multi-language-timings/cutgo.go b/scripts/perf/early-multi-language-timings/cutgo.go similarity index 100% rename from scripts/early-multi-language-timings/cutgo.go rename to scripts/perf/early-multi-language-timings/cutgo.go diff --git a/scripts/early-multi-language-timings/cutgo.go.txt b/scripts/perf/early-multi-language-timings/cutgo.go.txt similarity index 100% rename from scripts/early-multi-language-timings/cutgo.go.txt rename to scripts/perf/early-multi-language-timings/cutgo.go.txt diff --git a/scripts/early-multi-language-timings/cutnim.nim b/scripts/perf/early-multi-language-timings/cutnim.nim similarity index 100% rename from scripts/early-multi-language-timings/cutnim.nim rename to scripts/perf/early-multi-language-timings/cutnim.nim diff --git a/scripts/early-multi-language-timings/do-timings.rb b/scripts/perf/early-multi-language-timings/do-timings.rb similarity index 100% rename from scripts/early-multi-language-timings/do-timings.rb rename to scripts/perf/early-multi-language-timings/do-timings.rb diff --git a/scripts/early-multi-language-timings/ff1.rs b/scripts/perf/early-multi-language-timings/ff1.rs similarity index 89% rename from scripts/early-multi-language-timings/ff1.rs rename to scripts/perf/early-multi-language-timings/ff1.rs index cda208f0b..a78c18e4b 100644 --- a/scripts/early-multi-language-timings/ff1.rs +++ b/scripts/perf/early-multi-language-timings/ff1.rs @@ -20,5 +20,5 @@ fn read_lines_buf_reader(path: &str) -> io::Result<()> { } fn main() { - let _ = read_lines_buf_reader("/Users/kerl/tmp/big"); + let _ = read_lines_buf_reader("/Users/kerl/data/big"); } diff --git a/scripts/early-multi-language-timings/ff2.rs b/scripts/perf/early-multi-language-timings/ff2.rs similarity index 90% rename from scripts/early-multi-language-timings/ff2.rs rename to scripts/perf/early-multi-language-timings/ff2.rs index c83baecbc..87d010fff 100644 --- a/scripts/early-multi-language-timings/ff2.rs +++ b/scripts/perf/early-multi-language-timings/ff2.rs @@ -17,5 +17,5 @@ fn read_lines_manual(path: &str) -> io::Result<()> { } fn main() { - let _ = read_lines_manual("/Users/kerl/tmp/big"); + let _ = read_lines_manual("/Users/kerl/data/big"); } diff --git a/scripts/early-multi-language-timings/ff3.rs b/scripts/perf/early-multi-language-timings/ff3.rs similarity index 88% rename from scripts/early-multi-language-timings/ff3.rs rename to scripts/perf/early-multi-language-timings/ff3.rs index 835df7c40..2fecfe5da 100644 --- a/scripts/early-multi-language-timings/ff3.rs +++ b/scripts/perf/early-multi-language-timings/ff3.rs @@ -17,5 +17,5 @@ fn read_lines_custom_buffer(path: &str) -> io::Result<()> { } fn main() { - let _ = read_lines_custom_buffer("/Users/kerl/tmp/big"); + let _ = read_lines_custom_buffer("/Users/kerl/data/big"); } diff --git a/scripts/early-multi-language-timings/ff4.rs b/scripts/perf/early-multi-language-timings/ff4.rs similarity index 89% rename from scripts/early-multi-language-timings/ff4.rs rename to scripts/perf/early-multi-language-timings/ff4.rs index 4ee3224ee..418c13186 100644 --- a/scripts/early-multi-language-timings/ff4.rs +++ b/scripts/perf/early-multi-language-timings/ff4.rs @@ -20,5 +20,5 @@ fn read_lines_memmap(path: &str) -> io::Result<()> { } fn main() { - let _ = read_lines_custom_buffer("/Users/kerl/tmp/big"); + let _ = read_lines_custom_buffer("/Users/kerl/data/big"); } diff --git a/scripts/early-multi-language-timings/mand/mand.c b/scripts/perf/early-multi-language-timings/mand/mand.c similarity index 100% rename from scripts/early-multi-language-timings/mand/mand.c rename to scripts/perf/early-multi-language-timings/mand/mand.c diff --git a/scripts/early-multi-language-timings/mand/mand.mlr b/scripts/perf/early-multi-language-timings/mand/mand.mlr similarity index 100% rename from scripts/early-multi-language-timings/mand/mand.mlr rename to scripts/perf/early-multi-language-timings/mand/mand.mlr diff --git a/scripts/early-multi-language-timings/mand/mand.py b/scripts/perf/early-multi-language-timings/mand/mand.py similarity index 100% rename from scripts/early-multi-language-timings/mand/mand.py rename to scripts/perf/early-multi-language-timings/mand/mand.py diff --git a/scripts/early-multi-language-timings/mand/mand.rb b/scripts/perf/early-multi-language-timings/mand/mand.rb similarity index 100% rename from scripts/early-multi-language-timings/mand/mand.rb rename to scripts/perf/early-multi-language-timings/mand/mand.rb diff --git a/scripts/early-multi-language-timings/mand/mandg.go b/scripts/perf/early-multi-language-timings/mand/mandg.go similarity index 100% rename from scripts/early-multi-language-timings/mand/mandg.go rename to scripts/perf/early-multi-language-timings/mand/mandg.go diff --git a/scripts/early-multi-language-timings/mand/timings.txt b/scripts/perf/early-multi-language-timings/mand/timings.txt similarity index 100% rename from scripts/early-multi-language-timings/mand/timings.txt rename to scripts/perf/early-multi-language-timings/mand/timings.txt diff --git a/scripts/early-multi-language-timings/mkplots.sh b/scripts/perf/early-multi-language-timings/mkplots.sh similarity index 100% rename from scripts/early-multi-language-timings/mkplots.sh rename to scripts/perf/early-multi-language-timings/mkplots.sh diff --git a/scripts/perf/early-multi-language-timings/new-timings.sh b/scripts/perf/early-multi-language-timings/new-timings.sh new file mode 100644 index 000000000..f5b2d8479 --- /dev/null +++ b/scripts/perf/early-multi-language-timings/new-timings.sh @@ -0,0 +1,9 @@ +justtime ./catc < ~/data/big > /dev/null +justtime ./catc0 < ~/data/big > /dev/null +justtime ./catm < ~/data/big > /dev/null +justtime ./catrust < ~/data/big > /dev/null +justtime ./catrust2 < ~/data/big > /dev/null +justtime ./ff1 < ~/data/big > /dev/null +justtime ./ff2 < ~/data/big > /dev/null +justtime ./ff3 < ~/data/big > /dev/null +justtime ./catgo < ~/data/big > /dev/null diff --git a/scripts/early-multi-language-timings/new-timings.txt b/scripts/perf/early-multi-language-timings/new-timings.txt similarity index 86% rename from scripts/early-multi-language-timings/new-timings.txt rename to scripts/perf/early-multi-language-timings/new-timings.txt index bd095e95e..816444580 100644 --- a/scripts/early-multi-language-timings/new-timings.txt +++ b/scripts/perf/early-multi-language-timings/new-timings.txt @@ -20,5 +20,5 @@ TIME IN SECONDS 9.691 -- ./catc TIME IN SECONDS 12.975 -- ./catrust TIME IN SECONDS 52.282 -- ./catrust2 -$ justtime mlr cat ~/tmp/big > /dev/null -TIME IN SECONDS 79.106 -- mlr cat /Users/kerl/tmp/big +$ justtime mlr cat ~/data/big > /dev/null +TIME IN SECONDS 79.106 -- mlr cat /Users/kerl/data/big diff --git a/scripts/early-multi-language-timings/nimcat.nim.txt b/scripts/perf/early-multi-language-timings/nimcat.nim.txt similarity index 100% rename from scripts/early-multi-language-timings/nimcat.nim.txt rename to scripts/perf/early-multi-language-timings/nimcat.nim.txt diff --git a/scripts/early-multi-language-timings/nimcut.nim.txt b/scripts/perf/early-multi-language-timings/nimcut.nim.txt similarity index 100% rename from scripts/early-multi-language-timings/nimcut.nim.txt rename to scripts/perf/early-multi-language-timings/nimcut.nim.txt diff --git a/scripts/early-multi-language-timings/nimlc.nim b/scripts/perf/early-multi-language-timings/nimlc.nim similarity index 100% rename from scripts/early-multi-language-timings/nimlc.nim rename to scripts/perf/early-multi-language-timings/nimlc.nim diff --git a/scripts/early-multi-language-timings/nimwc.nim b/scripts/perf/early-multi-language-timings/nimwc.nim similarity index 100% rename from scripts/early-multi-language-timings/nimwc.nim rename to scripts/perf/early-multi-language-timings/nimwc.nim diff --git a/scripts/early-multi-language-timings/t1s.rb b/scripts/perf/early-multi-language-timings/t1s.rb similarity index 100% rename from scripts/early-multi-language-timings/t1s.rb rename to scripts/perf/early-multi-language-timings/t1s.rb diff --git a/scripts/early-multi-language-timings/timings.txt b/scripts/perf/early-multi-language-timings/timings.txt similarity index 100% rename from scripts/early-multi-language-timings/timings.txt rename to scripts/perf/early-multi-language-timings/timings.txt diff --git a/scripts/early-multi-language-timings/tn.rb b/scripts/perf/early-multi-language-timings/tn.rb similarity index 100% rename from scripts/early-multi-language-timings/tn.rb rename to scripts/perf/early-multi-language-timings/tn.rb diff --git a/scripts/make-data-stream b/scripts/perf/make-data-stream similarity index 98% rename from scripts/make-data-stream rename to scripts/perf/make-data-stream index 0e8c8485b..67a61d97f 100755 --- a/scripts/make-data-stream +++ b/scripts/perf/make-data-stream @@ -1,3 +1,5 @@ +#!/bin/bash + stop=1000000000 profile="" @@ -29,4 +31,3 @@ mlr \ then rename i,k \ then cut -xf index \ then filter '$rate > 2' - diff --git a/scripts/perf/prep-perf-data.sh b/scripts/perf/prep-perf-data.sh new file mode 100755 index 000000000..623517f36 --- /dev/null +++ b/scripts/perf/prep-perf-data.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Invoke from Miller repo base. + +set -x + +indir=./test/input +outdir=~/data +mkdir -p $outdir + +mlr --csv \ + --from docs/src/example.csv \ + repeat -n 100000 \ + then shuffle \ + then put ' + begin{@index=1} + $k = NR; + @index += urandint(2,10); + $index=@index; + $quantity=fmtnum(urandrange(50,100),"%.4f"); + $rate=fmtnum(urandrange(1,10),"%.4f"); + ' \ +> $outdir/big.csv + +mlr --csv head -n 1000 $outdir/big.csv > $outdir/small.csv +mlr --csv head -n 10000 $outdir/big.csv > $outdir/medium.csv + +for kind in small medium big; do + mlr --c2d cat $outdir/$kind.csv > $outdir/$kind.dkvp + mlr --c2n cat $outdir/$kind.csv > $outdir/$kind.nidx + mlr --c2x cat $outdir/$kind.csv > $outdir/$kind.xtab + mlr --c2j cat $outdir/$kind.csv > $outdir/$kind.json +done diff --git a/scripts/perf/time-verbs.py b/scripts/perf/time-verbs.py new file mode 100755 index 000000000..0dc31e6f4 --- /dev/null +++ b/scripts/perf/time-verbs.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +import os +import sys +import time +import subprocess + +# ================================================================ +def main(): + mlrs = [ "mlr" ] + # + kind = "big" + #kind = "medium" + #kind = "small" + in_csv = f"$HOME/data/{kind}.csv" + in_csvlite = f"$HOME/data/{kind}.csv" + in_dkvp = f"$HOME/data/{kind}.dkvp" + in_nidx = f"$HOME/data/{kind}.nidx" + in_xtab = f"$HOME/data/{kind}.xtab" + in_json = f"$HOME/data/{kind}.json" + # + cases = [ + ["check", f"--csv --from {in_csv} check"], + ["cat", f"--csv --from {in_csv} cat"], + ["tail", f"--csv --from {in_csv} tail"], + ["tac", f"--csv --from {in_csv} tac"], + ["sort-f", f"--csv --from {in_csv} sort -f shape"], + ["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"], + None, + ["cat-csv", f"--csv --from {in_csv} cat"], + ["cat-csvlite", f"--csvlite --from {in_csvlite} cat"], + ["cat-dkvp", f"--dkvp --from {in_dkvp} cat"], + ["cat-nidx", f"--nidx --from {in_nidx} cat"], + ["cat-xtab", f"--xtab --from {in_xtab} cat"], + ["cat-json", f"--json --from {in_json} cat"], + ] + # + nreps = 5 + + if len(sys.argv) > 1: + mlrs = sys.argv[1:] + + + for case in cases: + if case is None: + print() + continue + for mlr in mlrs: + desc, args = case + avg = time_runs(desc, mlr, args, nreps) + print(f"desc={desc},version={mlr},seconds={avg:.3f}") + +# ---------------------------------------------------------------- +def time_runs(desc, mlr, args, nreps): + args = os.path.expandvars(args) + cmd = f"{mlr} {args}" + times = [time_run(mlr, args) for _ in range(nreps)] + avg = sum(times) / len(times) + return avg + +# ---------------------------------------------------------------- +def time_run(mlr, args): + cmd = f"{mlr} {args} > /dev/null" + start = time.perf_counter() + subprocess.run(cmd, shell=True) + elapsed = time.perf_counter() - start + return elapsed + +# ================================================================ +if __name__ == "__main__": + main() diff --git a/scripts/perf/timings-2026-02-22.dat b/scripts/perf/timings-2026-02-22.dat new file mode 100644 index 000000000..2a7b97af9 --- /dev/null +++ b/scripts/perf/timings-2026-02-22.dat @@ -0,0 +1,85 @@ +desc=check,version=mlr-5.10.3,seconds=0.839 +desc=check,version=mlr-6.0.0,seconds=0.726 +desc=check,version=mlr-6.8.0,seconds=0.674 +desc=check,version=mlr-6.16.0,seconds=0.814 +desc=check,version=mlr-6.17.0,seconds=0.761 +desc=cat,version=mlr-5.10.3,seconds=1.439 +desc=cat,version=mlr-6.0.0,seconds=0.812 +desc=cat,version=mlr-6.8.0,seconds=0.763 +desc=cat,version=mlr-6.16.0,seconds=0.864 +desc=cat,version=mlr-6.17.0,seconds=0.820 +desc=tail,version=mlr-5.10.3,seconds=0.904 +desc=tail,version=mlr-6.0.0,seconds=0.757 +desc=tail,version=mlr-6.8.0,seconds=0.694 +desc=tail,version=mlr-6.16.0,seconds=0.845 +desc=tail,version=mlr-6.17.0,seconds=0.782 +desc=tac,version=mlr-5.10.3,seconds=1.603 +desc=tac,version=mlr-6.0.0,seconds=1.807 +desc=tac,version=mlr-6.8.0,seconds=1.943 +desc=tac,version=mlr-6.16.0,seconds=1.997 +desc=tac,version=mlr-6.17.0,seconds=1.275 +desc=sort-f,version=mlr-5.10.3,seconds=1.719 +desc=sort-f,version=mlr-6.0.0,seconds=1.939 +desc=sort-f,version=mlr-6.8.0,seconds=1.768 +desc=sort-f,version=mlr-6.16.0,seconds=1.716 +desc=sort-f,version=mlr-6.17.0,seconds=1.374 +desc=sort-n,version=mlr-5.10.3,seconds=2.914 +desc=sort-n,version=mlr-6.0.0,seconds=5.992 +desc=sort-n,version=mlr-6.8.0,seconds=2.782 +desc=sort-n,version=mlr-6.16.0,seconds=2.781 +desc=sort-n,version=mlr-6.17.0,seconds=2.491 +desc=stats1,version=mlr-5.10.3,seconds=1.827 +desc=stats1,version=mlr-6.0.0,seconds=1.077 +desc=stats1,version=mlr-6.8.0,seconds=1.095 +desc=stats1,version=mlr-6.16.0,seconds=1.112 +desc=stats1,version=mlr-6.17.0,seconds=0.903 +desc=chain-1,version=mlr-5.10.3,seconds=3.782 +desc=chain-1,version=mlr-6.0.0,seconds=1.382 +desc=chain-1,version=mlr-6.8.0,seconds=1.413 +desc=chain-1,version=mlr-6.16.0,seconds=1.637 +desc=chain-1,version=mlr-6.17.0,seconds=1.603 +desc=chain-2,version=mlr-5.10.3,seconds=5.959 +desc=chain-2,version=mlr-6.0.0,seconds=1.658 +desc=chain-2,version=mlr-6.8.0,seconds=1.628 +desc=chain-2,version=mlr-6.16.0,seconds=1.771 +desc=chain-2,version=mlr-6.17.0,seconds=1.709 +desc=chain-3,version=mlr-5.10.3,seconds=7.869 +desc=chain-3,version=mlr-6.0.0,seconds=1.982 +desc=chain-3,version=mlr-6.8.0,seconds=1.915 +desc=chain-3,version=mlr-6.16.0,seconds=2.015 +desc=chain-3,version=mlr-6.17.0,seconds=1.926 +desc=chain-4,version=mlr-5.10.3,seconds=10.188 +desc=chain-4,version=mlr-6.0.0,seconds=2.236 +desc=chain-4,version=mlr-6.8.0,seconds=2.162 +desc=chain-4,version=mlr-6.16.0,seconds=2.277 +desc=chain-4,version=mlr-6.17.0,seconds=2.156 +desc=cat-csv,version=mlr-5.10.3,seconds=1.525 +desc=cat-csv,version=mlr-6.0.0,seconds=0.865 +desc=cat-csv,version=mlr-6.8.0,seconds=0.805 +desc=cat-csv,version=mlr-6.16.0,seconds=0.898 +desc=cat-csv,version=mlr-6.17.0,seconds=0.840 +desc=cat-csvlite,version=mlr-5.10.3,seconds=0.950 +desc=cat-csvlite,version=mlr-6.0.0,seconds=0.939 +desc=cat-csvlite,version=mlr-6.8.0,seconds=0.892 +desc=cat-csvlite,version=mlr-6.16.0,seconds=1.008 +desc=cat-csvlite,version=mlr-6.17.0,seconds=0.944 +desc=cat-dkvp,version=mlr-5.10.3,seconds=1.526 +desc=cat-dkvp,version=mlr-6.0.0,seconds=1.216 +desc=cat-dkvp,version=mlr-6.8.0,seconds=1.186 +desc=cat-dkvp,version=mlr-6.16.0,seconds=1.257 +desc=cat-dkvp,version=mlr-6.17.0,seconds=1.207 +desc=cat-nidx,version=mlr-5.10.3,seconds=0.915 +desc=cat-nidx,version=mlr-6.0.0,seconds=0.940 +desc=cat-nidx,version=mlr-6.8.0,seconds=2.675 +desc=cat-nidx,version=mlr-6.16.0,seconds=2.770 +desc=cat-nidx,version=mlr-6.17.0,seconds=3.177 +desc=cat-xtab,version=mlr-5.10.3,seconds=3.159 +desc=cat-xtab,version=mlr-6.0.0,seconds=1.125 +desc=cat-xtab,version=mlr-6.8.0,seconds=1.166 +desc=cat-xtab,version=mlr-6.16.0,seconds=1.228 +desc=cat-xtab,version=mlr-6.17.0,seconds=1.118 +desc=cat-json,version=mlr-5.10.3,seconds=6.319 +desc=cat-json,version=mlr-6.0.0,seconds=16.032 +desc=cat-json,version=mlr-6.8.0,seconds=9.723 +desc=cat-json,version=mlr-6.16.0,seconds=8.637 +desc=cat-json,version=mlr-6.17.0,seconds=8.663 diff --git a/scripts/perf/timings-2026-02-22.sh b/scripts/perf/timings-2026-02-22.sh new file mode 100644 index 000000000..b354238f7 --- /dev/null +++ b/scripts/perf/timings-2026-02-22.sh @@ -0,0 +1,16 @@ +datafile=timings-2026-02-22.dat + +mlr --d2p --from $datafile \ + grep cat then reshape -s desc,seconds \ + | sed '1s/^/#/' \ + | pgr -cat -flabels -lul -lp -ms 5 -o cats.png & + +mlr --d2p --from $datafile \ + grep chain then reshape -s desc,seconds \ + | sed '1s/^/#/' \ + | pgr -cat -flabels -lul -lp -ms 5 -o chains.png & + +mlr --d2p --from $datafile \ + grep -v cat then grep -v chain then reshape -s desc,seconds \ + | sed '1s/^/#/' \ + | pgr -cat -flabels -lul -lp -ms 5 -o verbs.png & diff --git a/scripts/time-big-file b/scripts/time-big-file deleted file mode 100755 index fef1e07ca..000000000 --- a/scripts/time-big-file +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -mlr="mlr" -suffix="dkvp" - -iflag="" -if [ $# -ge 1 ]; then - iflag="--$1" - if [ "$iflag" = "--csvlite" ]; then - suffix="csv" - else - suffix=$1 - fi -fi -if [ $# -eq 2 ]; then - mlr="$2" -fi -justtime $mlr $iflag cat ~/tmp/big.$suffix > /dev/null diff --git a/scripts/time-big-files b/scripts/time-big-files deleted file mode 100755 index 7f761c794..000000000 --- a/scripts/time-big-files +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -ourdir=$(dirname $0) - -mlrs="mlr" -if [ $# -ge 1 ]; then - mlrs="$@" -fi -#mlrs="mlr5 ./mlr" - -#reps="1" -reps="1 2 3" - -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file csv $mlr; done; done -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file csvlite $mlr; done; done -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file dkvp $mlr; done; done -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file nidx $mlr; done; done -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file xtab $mlr; done; done -echo; for mlr in $mlrs; do for k in $reps; do $ourdir/time-big-file json $mlr; done; done -