Contact:
koala@brown.eduor open a GitHub issue.
Koala is a benchmark suite aimed at the characterization of performance-oriented research targeting the POSIX shell (i.e. executable on Dash, Bash, Zsh, and many other environments). It combines a systematic collection of diverse shell programs collected from tasks found out in the wild, various real inputs to these programs.
Artifact evaluation:
To evaluate key results in our ATC'25 paper titled "The Koala Benchmarks for the Shell: Characterization and Implications", jump straight to
INSTRUCTIONS/.
Update: The Koala benchmark suite received all USENIX ATC Artifact Evaluation badges:
| Benchmark | Description |
|---|---|
aurpkg |
AUR package builds. |
bio |
Bioinformatics. |
covid-mts |
COVID-19 multivariate time series. |
file-enc |
File encoding. |
log-analysis |
Log analysis. |
makeself |
Make self-extractable archives on Unix. |
max-temp |
Maximum temperature. |
media-conv |
Media conversion. |
nlp |
Natural language processing. |
oneliners |
One-liners. |
riker |
Incremental builds. |
sklearn |
Machine learning. |
vps-audit |
Audit a Linux machine. |
unix50 |
Unix 50. |
web-index |
Web index. |
The top-level main.sh script is a quick script for downloading dependencies and inputs, running, profiling, and verifying a single Koala benchmark.
./main.sh <BENCHMARK_NAME> [OPTIONS] [<args passed to execute.sh>]To support the diverse landscape of shell programs and shell-related research, the Koala benchmark suite is designed with flexibility and simplicity in mind.
Its infrastructure is deliberately minimal and easy to modify, making it adaptable to a wide variety of systems and use cases. As it cannot anticipate all potential applications, Koala encourages users to modify any part of the infrastructure to better suit their needs.
For example, given the following (example) benchmark:
# example-benchmark/scripts/x.sh
cat file.txt | grep "foo" | wc -lSomeone experimenting with GNU parallel might want to modify the script as follows:
# example-benchmark/scripts/x.sh
cat file.txt | parallel --pipe grep "foo" | wc -lSimilalary, a research team developing a distributed shell can modify the script to:
# example-benchmark/scripts/x.sh
hdfs dfs -cat file.txt | dsh --pipe grep "foo" | wc -lFor systems that act as a drop-in replacement for the shell can use Koala's benchmarks by overriding the $KOALA_SHELL variable to point to their system.
For example, to apply the PaSh system to the Koala benchmarks, one can do:
$ export KOALA_SHELL="./pa.sh --width 4"
$ ./main.sh example-benchmarkEach benchmark directory contains:
benchmarks/<name>/
├── scripts/ # Benchmark scripts (*.sh)
├── install.sh # Installs dependencies
├── fetch.sh # Fetches input data
├── execute.sh # Runs benchmark
├── validate.sh # Validates output via hashes
└── clean.sh # Cleans temporary files (input and output files)
To manually execute a single benchmark:
cd benchmarks/<name>
./install.sh
# This will place input data in the `benchmarks/<name>/inputs` folder
./fetch.sh
# This will run one by one all scripts inside `benchmarks/<name>/scripts/` folder
# Any output files produced will be placed in the `benchmarks/<name>/outputs` folder
./execute.sh
# This will check the output files against the expected hashes, and print the results
# For benchmarks that do not produce output files, specialized validation logic is used
./validate.sh
# This will remove all temporary files created by the benchmark
# By default, it will remove both inputs and outputs, returning the benchmark folder in its original state
./clean.shThe harness which automates this process and collects/displays metrics is main.sh:
benchmarks/main.sh # Drives all benchmarks
Configuration options (via env or CLI):
To control the shell interpreter used to run the benchmarks, you can set the
KOALA_SHELL environment variable.
Note: The setup scripts in this suite are designed for Debian-based systems. Koala comes with a Docker image, highly recommended when working on non-Debian systems.
To build and run the Docker image:
# Build the container
$ docker build -t koala .
# Run the container
$ docker run -it koala
# For development, mount the benchmarks directory
$ docker run -it -v "$(pwd):/benchmarks" koalaUsage: ./main.sh BENCHMARK_NAME [--time|--resources|--bare|args...]
--min Run the benchmark with minimal inputs (default)
--small Run the benchmark with small inputs
--full Run the benchmark with full inputs
--time, -t Measure wall-clock time
--resources Measure resource usage
--bare Run locally without Docker
--runs, -n N Number of runs (default: 1)
--clean, -c Run the full cleanup script (both inputs and outputs)
--keep, -k Keep outputs
--prune Run the benchmark on a fresh container (will need to re-download everything on each run)
--help, -h Show this help message
Flags, apart from those referring to input sizes, can be combined freely (e.g. --resources --bare -n 5).
| File (per-run) | Contents / Purpose | Generated when … |
|---|---|---|
<benchmark>.out / <benchmark>.err |
Stdout / stderr from execute.sh. |
Always |
benchmark.hash |
Pass/fail hashes written by validate.sh – indicates whether the run was correct. |
Always |
logs/… (folder) |
Raw monitors: *.pidstat, *.io, *.cpu, *.mem, *.time, *.val. |
Only with (--resources or --time) && --bare |
<prefix>_stats_run<i>.txt |
Human-readable CPU/RAM/I/O summary for run i. | Only with --resources |
<benchmark>_time_run<i>.val |
Single wall-clock number (seconds) for run i. | Only with --time |
| File (aggregated) | Description | Requires flag |
|---|---|---|
<prefix>_stats_aggregated.txt |
Mean / min / max of every numeric resource metric. | --resources |
<benchmark>_times_aggregated.txt |
Mean / min / max of wall-clock seconds. | --time |
- Plain correctness run for the
unix50benchmark:
./main.sh unix50- Run 10 times, record runtimes only:
./main.sh unix50 -n 10 --time- Heavy resource tracing inside Docker – 3 repetitions:
./main.sh unix50 -n 3 --resources- Lightweight local resource logging (no Docker):
./main.sh unix50 --resources --bare- Combine timing + resources, forward extra args to benchmark's infrastructure scripts:
./main.sh unix50 -n 5 --resources --time -- --small --fastWhen running a benchmark with the --resources flag, existing process logs in infrastructure/target/process-logs/ are automatically moved to infrastructure/target/backup-process-logs/.
This ensures clean output when collecting new resource statistics. The new logs are then used to generate dynamic analysis visualizations.
You can also run the dynamic analysis independently of the main harness. This is useful for manually generating plots and debugging, while only having to execute each benchmark and avoiding the full setup and cleanup process.
-
Install dependencies:
sudo apt-get install -y autoconf automake libtool build-essential cloc pip install --break-system-packages -r "infrastructure/requirements.txt" -
Run the analysis script manually:
./infrastructure/run_dynamic.py benchmark_name
This generates new process logs in:
infrastructure/target/process-logs/
-
(If using Docker):
Copy the log files from the container to your host system in order to generate plots. The requirements will need to be installed in your host machine as well.
If you'd prefer not to copy files, you can instead run the visualizer with the--textflag to produce textual output directly:infrastructure/viz/dynamic.py --text
-
Navigate to the infrastructure directory:
cd infrastructure -
Delete previous analysis output:
rm -f target/dynamic_analysis.csv
-
Regenerate the analysis CSV:
make target/dynamic_analysis.csv
-
Generate the visualizations:
python infrastructure/viz/dynamic.py /path/to/output
This produces benchmark-specific performance plots, showing shell vs command time,
CPU usage, I/O throughput, and memory footprint, for all benchmarks that have logs present in infrastructure/target/process-logs/
Benchmark Statistics
==================================================
Benchmark: bio
--------------------------------------------------
Total CPU time: 6.68 sec
Total Wall time: 6.91 sec
Total IO bytes: 1107624733.00
Max Memory Usage: 17235968.00 bytes
CPU time per input byte: 0.000000 sec/byte
Memory per input byte: 0.071815 bytes/byte
IO per input byte: 4.615032 bytes/byte
Time in Shell: 0.00 sec
Time in Commands: 6.68 sec
==================================================
Per-input-byte numbers are computed automatically: if BENCHMARK_INPUT_FILE points to a file or a directory, the harness figures out its byte size.
For more accurate analysis, please run inside a docker container.
Local (--bare) and Docker-based stats share the exact same format, so they aggregate seamlessly.
We use libdash to parse and analyze both the shell portion of each benchmark, and the portions of components called into by the shell and which often implement the kernel of a computation: for the shell portion, we count the total occurrences of every AST node; for the command portion, we analyze only AST nodes counting commands, built-ins, and functions—noting that the results are conservative, as they do not count dynamic commands.
The analysis produces CSV summaries and heatmaps across the benchmark suite, highlighting the use of each shell construct.
-
Install dependencies:
sudo apt-get install -y autoconf automake libtool build-essential cloc pip install --break-system-packages -r infrastructure/requirements.txt
-
Register the benchmark script:
Add the new benchmark’s script pattern to:infrastructure/data/script-globs.jsonNote: Syntactic analysis only works for POSIX-compliant scripts.
-
Remove previous analysis artifacts:
rm -f infrastructure/target/cyclomatic.csv rm -f infrastructure/target/lines_of_code.csv rm -f infrastructure/target/nodes_in_scripts.csv rm -f infrastructure/target/scripts_to_benchmark.csv
-
Navigate to the infrastructure directory:
cd infrastructure -
Regenerate the syntactic analysis artifacts:
make -
Generate visualizations:
python infrastructure/viz/syntax.py output_dir python infrastructure/viz/commands.py output_dir
These will produce plots summarizing shell syntax usage and external command invocation patterns for all registered benchmarks in the specified output_dir.
The Koala Benchmarks are licensed under the MIT License. See the LICENSE file for more information.