Help us shape the future of Go! Take the 2026 Go Developer Survey

stressy

command module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2026 License: MIT Imports: 2 Imported by: 0

README

stressy

CI Latest release Go version

A CPU stress tool. It loads every CPU it is given with bcrypt hashing and reports the rate, so the same run on two nodes is a comparison.

stress-ng has 300 stressors; stressy has one and deploys anywhere — a 2.8 MB static binary for twelve OS/architecture targets, and a FROM scratch image with no base layer, no package manager, no shell and a non-root UID.

Install

go install github.com/felipeneuwald/stressy@latest
docker pull ghcr.io/felipeneuwald/stressy:latest

Or a prebuilt binary.

Usage

# Load every usable CPU until interrupted
stressy

# Four workers for five minutes
stressy -w 4 -t 5m

# Any Go duration; a bare number is seconds, so pre-0.4 command lines still work
stressy -t 1h30m
stressy -t 60

# A progress line every 30 seconds
stressy -t 30m -r 30s

# The same settings from the environment
export STRESSY_WORKERS=4
export STRESSY_TIMEOUT=5m
stressy

A flag given on the command line beats its environment variable, and an empty variable counts as unset — so STRESSY_WORKERS=${WORKERS} with WORKERS undefined leaves the default in place rather than failing the run.

Output

A run says what it is about to do, why it stopped, and what it did:

$ stressy -w 4 -t 60s
Starting CPU stress test with 4 workers for 60s
Timer expired, shutting down...
Computed 1324 hashes in 1m0.101s (22.0 hashes/s, 4 workers)

A run with no -t says how to stop it, and still reports what it managed:

$ stressy -w 4
Starting CPU stress test with 4 workers indefinitely
Press Ctrl+C or send SIGTERM to stop. Use --help for additional information
^C
Received signal, shutting down...
Computed 412 hashes in 18.734s (22.0 hashes/s, 4 workers)

Because bcrypt at a fixed cost is constant work per hash, that rate is a crude cross-node benchmark: a node hashing 30% slower is a finding.

Between those lines a run says nothing, so -r, --report fills the gap:

$ stressy -w 4 -t 2m --report 1m
Starting CPU stress test with 4 workers for 2m0s
1m0.001s elapsed, 1320 hashes, 22.0 hashes/s
2m0.001s elapsed, 2636 hashes, 22.0 hashes/s
Timer expired, shutting down...
Computed 2640 hashes in 2m0.093s (22.0 hashes/s, 4 workers)
Containers
# Bounded run: 30 seconds, then the container exits on its own
docker run --rm ghcr.io/felipeneuwald/stressy:latest -t 30s

# Two CPUs' worth of load for five minutes, configured by the environment
docker run --rm --cpus 2 -e STRESSY_TIMEOUT=5m ghcr.io/felipeneuwald/stressy:latest

Both are bounded, deliberately: with no timeout, docker run -d leaves a container loading every CPU it can reach until somebody runs docker stop.

The worker count is read from the cgroup CPU quota, not the host's core count, so --cpus 2 on a 16-core host starts 2 workers and limits.cpu: "2" in a pod spec starts 2 as well — -w is redundant there, and above the limit it buys throttling rather than load. The floor is 2, so --cpus 1 starts 2.

In Kubernetes a Job is the shape this fits: one pod, run to exit 0, recorded as finished — which makes -t and the exit codes load-bearing, since a pod evicted, preempted or kubectl deleted part-way through exits 143.

apiVersion: batch/v1
kind: Job
metadata:
  name: stressy
spec:
  # A run that failed should not be retried indefinitely at full CPU.
  backoffLimit: 0
  # Clear the finished Job an hour after it completes.
  ttlSecondsAfterFinished: 3600
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: stressy
          image: ghcr.io/felipeneuwald/stressy:latest
          args: ["-t", "60s"]
          resources:
            limits:
              cpu: "2"
              memory: 64Mi
            requests:
              cpu: "2"
              memory: 64Mi
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop: ["ALL"]
            seccompProfile:
              type: RuntimeDefault
      securityContext:
        runAsNonRoot: true
kubectl apply -f stressy-job.yaml
kubectl logs -l batch.kubernetes.io/job-name=stressy

Those four securityContext fields are what the restricted Pod Security Standard requires, and the whole of it: runAsUser is not among them, because the image already runs as UID/GID 65532. It is FROM scratch, so there is no shell to kubectl exec in with and stdout is the only view you have of a run — which is what --report is for. :latest only ever points at a full release.

Available Flags
  • -w, --workers: Number of parallel workers (must be 1 or greater). Defaults to the number of CPUs this process can use — the host's core count, narrowed by the CPU affinity mask, by a cgroup CPU limit if there is one, and by the GOMAXPROCS environment variable if it is set. stressy --help prints the number for the machine you run it on
  • -t, --timeout: How long to run, as a duration such as 30s, 5m or 1h30m. A bare number is read as seconds, so -t 60 still means one minute. 0, the default, runs until interrupted
  • -r, --report: Print a progress line this often — elapsed time, hashes computed and rate. Takes the same duration spellings --timeout does, a bare number included. 0, the default, prints none, which is what a run has always done
  • -h, --help: Show help information
  • -v, --version: Show version information
Exit codes
Code Meaning
0 The run served the whole --timeout it was given
1 The configuration was rejected — an unknown flag, an unparseable value, an unexpected argument — and no work was done
130 SIGINT cut the run short, which is 128 + 2 and what Ctrl-C sends
143 SIGTERM cut the run short, which is 128 + 15 and what docker stop, a kubectl delete pod and a node drain send

Building from Source

git clone https://github.com/felipeneuwald/stressy.git
cd stressy
go build
./stressy -t 5s

Contributing

CONTRIBUTING.md has the checks CI runs and the conventions.

Security

Please do not open a public issue for a vulnerability. SECURITY.md says what is in scope and how to report privately.

License

MIT — see LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
cli
stressy
Package stressy runs CPU stress tests with worker goroutines that hash bcrypt.
Package stressy runs CPU stress tests with worker goroutines that hash bcrypt.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL