Skip to content

gfleury/greb

Repository files navigation

greb - gfleury's remote execution benchmark

A CLI tool for stress-testing Buildbarn (and other REv2-compatible) remote execution clusters. It ships a local directory as input, crafts uniquely salted actions to guarantee cache misses, and ramps up concurrency over time to find the cluster's saturation point.

Installation

go install github.com/gfleury/greb/cmd/greb@latest

Or build from source:

git clone https://github.com/gfleury/greb.git
cd greb
go build ./cmd/greb

Building with Bazel

greb uses Bazel with bzlmod (MODULE.bazel). Bazelisk is recommended to automatically fetch the pinned Bazel version.

# Build the binary
bazel build //cmd/greb

# Run directly
bazel run //cmd/greb -- --help

# Build all targets
bazel build //...

To regenerate BUILD files after changing Go imports or dependencies:

bazel run //:gazelle

Quick Start

# Run 100 actions against a local Buildbarn cluster
greb --endpoint localhost:8980 --no-security \
     --command "/bin/echo,hello" \
     --total-actions 100

# Ship a directory, ramp up concurrency, export JSON
greb --endpoint localhost:8980 --no-security \
     --command "/bin/bash,-c,ls -la && sha256sum *" \
     --input-dir ./test-inputs \
     --total-actions 500 \
     --max-concurrency 40 --ramp-start 5 --ramp-step 5 --ramp-interval 10s \
     --salt-mode both \
     --output results.json --verbose

Usage

greb [flags]

Connection Flags

Flag Default Description
--endpoint (required) gRPC endpoint (e.g. localhost:8980)
--instance-name "" RE API instance name
--no-security false Disable TLS (plaintext gRPC)
--no-auth false TLS without authentication
--tls-ca-cert TLS CA certificate file
--tls-server-name Override TLS server name
--tls-client-cert mTLS client certificate file
--tls-client-key mTLS client key file

Action Flags

Flag Default Description
--command (required) Command to execute, comma-separated (e.g. /bin/bash,-c,echo hello)
--input-dir Local directory to ship as the action's input root
--platform Platform properties as key=value,key=value
--action-timeout 10m Per-action execution timeout

Benchmark Flags

Flag Default Description
--total-actions (required) Total number of actions to dispatch
--max-concurrency 50 Maximum number of concurrent workers
--ramp-start 1 Initial number of concurrent workers
--ramp-step 1 Number of workers to add each ramp interval
--ramp-interval 10s Time between ramp-up steps

Cache Busting Flags

Flag Default Description
--salt-mode env Cache busting strategy: env, file, or both

Output Flags

Flag Default Description
--output Path for JSON report file
--verbose false Log each action's result and timing to stderr

How It Works

Action Construction

Each action submitted to the remote execution cluster consists of:

  1. Input root -- If --input-dir is specified, the directory tree is uploaded to the Content Addressable Storage (CAS) and used as the action's input root. Files are uploaded once and reused across actions since only the salt changes.
  2. Command -- The --command arguments, environment variables, and platform properties are serialized into a Command proto and uploaded to CAS.
  3. Action -- References the Command digest and input root digest. Because each action is uniquely salted, every Action digest is different, guaranteeing no cache hits.

Cache Busting

Every action must have a unique digest to avoid being served from the Action Cache. greb supports three salting strategies:

  • env -- Adds a unique GREB_SALT=<uuid> environment variable to each action's Command. This changes the Command digest, which changes the Action digest.
  • file -- Adds a virtual .greb-salt file with random content to the input root. This changes the input root digest, which changes the Action digest. The file is injected in-memory via the SDK's VirtualInput mechanism (no temp files on disk).
  • both -- Applies both strategies simultaneously.

Additionally, all actions are submitted with DoNotCache: true and AcceptCached: false to avoid polluting or reading from the Action Cache.

Ramp-Up Concurrency

Instead of launching all workers at once, greb gradually increases concurrency to help identify the cluster's saturation point:

  1. Starts with --ramp-start workers
  2. Every --ramp-interval, adds --ramp-step more workers
  3. Caps at --max-concurrency
  4. All action indices are pre-loaded into a buffered channel; workers consume from it until drained

This produces metrics at varying concurrency levels, making it possible to observe how throughput and latency change as load increases.

Graceful Shutdown

Pressing Ctrl+C (SIGINT/SIGTERM) stops dispatching new actions but lets in-flight actions complete. Partial results are then reported normally.

Output

Summary (stdout)

=== greb Benchmark Results ===

Total actions:    100
Successful:       98 (98.0%)
Failed:           2
Total duration:   1m42s
Throughput:       0.98 actions/sec
Peak concurrency: 20

--- End-to-End Latency ---
  Min:    1.203s
  Mean:   4.512s
  P50:    3.891s
  P95:    9.203s
  P99:    12.44s
  Max:    14.02s

--- Phase Breakdown (p50) ---
  Upload:     120ms
  Queue:      2.1s
  Execution:  1.5s
  Download:   8ms

JSON Report (--output)

The JSON file contains the full benchmark data:

{
  "config": {
    "endpoint": "localhost:8980",
    "command": "/bin/echo hello",
    "total_actions": 100,
    "max_concurrency": 20,
    "salt_mode": "env"
  },
  "summary": {
    "total_actions": 100,
    "success_count": 98,
    "throughput_actions_per_sec": 0.98,
    "p50_latency_ms": 3891000000,
    "p95_latency_ms": 9203000000
  },
  "actions": [
    {
      "index": 0,
      "worker_id": 1,
      "total_duration_ms": 4512000000,
      "success": true,
      "timings": {
        "upload_ms": 120000000,
        "queue_wait_ms": 2100000000,
        "execution_ms": 1500000000,
        "download_ms": 8000000
      }
    }
  ],
  "concurrency_events": [
    {"timestamp": "2025-01-15T10:00:00Z", "concurrency": 2},
    {"timestamp": "2025-01-15T10:00:10Z", "concurrency": 4}
  ]
}

License

MIT

About

CLI stress-testing tool for Buildbarn and REv2-compatible remote execution clusters. Dispatches uniquely salted actions with ramp-up concurrency to find saturation points, reporting throughput, latency percentiles, and phase breakdowns.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors