Project

hey.rb

0.0
The project is in a healthy, maintained state
hey sends load to a web application and reports a latency histogram, percentile distribution and per-phase timings. A file-by-file Ruby port of rakyll/hey: goroutines and channels become Async tasks and queues, and net/http becomes async-http. The gem is named hey.rb because hey was taken.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

~> 0.2
~> 2.46
~> 0.105
~> 0.3
>= 4.0, < 7
 Project Readme

hey

hey is a tiny program that sends some load to a web application.

This is a Ruby port of rakyll/hey, translated file by file from the Go original. It is built on async-http: Go's goroutines and channels become Async tasks and queues, and net/http becomes Async::HTTP::Client.

hey was originally called boom and was influenced from Tarek Ziade's tool at tarekziade/boom. Using the same name was a mistake as it resulted in cases where binary name conflicts created confusion. To preserve the name for its original owner, we renamed this project to hey.

Installation

Requires Ruby 3.2 or later. The gem is named hey.rb, because hey was already taken; the command it installs is hey.

gem install hey.rb
hey https://google.com

From a checkout:

git clone https://github.com/n-at-han-k/hey.rb
cd hey.rb
bundle install
./exe/hey https://google.com

With Nix, the included flake provides a dev shell with every dependency:

nix develop
./exe/hey https://google.com

Usage

hey runs provided number of requests in the provided concurrency level and prints stats.

It also supports HTTP2 endpoints.

Usage: hey [options...] <url>

Options:
  -n  Number of requests to run. Default is 200.
  -c  Number of workers to run concurrently. Total number of requests cannot
      be smaller than the concurrency level. Default is 50.
  -q  Rate limit, in queries per second (QPS) per worker. Default is no rate limit.
  -z  Duration of application to send requests. When duration is reached,
      application stops and exits. If duration is specified, n is ignored.
      Examples: -z 10s -z 3m.
  -o  Output type. If none provided, a summary is printed.
      "csv" is the only supported alternative. Dumps the response
      metrics in comma-separated values format.

  -m  HTTP method, one of GET, POST, PUT, DELETE, HEAD, OPTIONS.
  -H  Custom HTTP header. You can specify as many as needed by repeating the flag.
      For example, -H "Accept: text/html" -H "Content-Type: application/xml" .
  -t  Timeout for each request in seconds. Default is 20, use 0 for infinite.
  -A  HTTP Accept header.
  -d  HTTP request body.
  -D  HTTP request body from file. For example, /home/user/file.txt or ./file.txt.
  -T  Content-type, defaults to "text/html".
  -U  User-Agent, defaults to version "hey/0.0.1".
  -a  Basic authentication, username:password.
  -x  HTTP Proxy address as host:port.
  -h2 Enable HTTP/2.

  -host	HTTP Host header.

  -disable-compression  Disable compression.
  -disable-keepalive    Disable keep-alive, prevents re-use of TCP
                        connections between different HTTP requests.
  -disable-redirects    Disable following of HTTP redirects
  -cpus                 Number of used cpu cores.
                        (default for current machine is 4 cores)

Examples

Make requests with default settings:

hey https://google.com

Make 1000 requests with 100 concurrent workers:

hey -n 1000 -c 100 https://google.com

Run load test for 30 seconds:

hey -z 30s https://google.com

Make POST request with custom body:

hey \
    -m POST \
    -d "param1=value1&param2=value2" \
    https://google.com

Add custom headers:

hey \
    -H "Accept: application/json" \
    -H "Authorization: Bearer token" \
    https://google.com

Test with HTTP/2:

hey -h2 https://google.com

Rate limit to 10 queries per second per worker:

hey -q 10 -c 5 -z 30s https://google.com

Dump per-request metrics as CSV:

hey -n 1000 -o csv https://google.com

Development

rspec

Notes on the port

The translation is file for file, and the summary and CSV output are byte-identical to the Go original's, including two quirks that were kept rather than fixed:

  • The latency distribution prints %% where a single % was intended, and a percentile that was not reached prints as a 0% row.
  • In the "Details" block the columns labelled fastest and slowest are the other way round for every stage except the overall figures.

-a (basic authentication) also has no effect, because hey.go replaces the request's header set after writing the Authorization header. Setting the header explicitly with -H "Authorization: ..." works.

Three flags differ because the runtime does:

  • -cpus is accepted and ignored; async runs on a single thread per process.
  • -x tunnels via HTTP CONNECT, so the DNS and connection timings reported for a proxied run are not meaningful.
  • Request-write and response-wait timings are derived from when async-http finishes writing the body and returns response headers, rather than from net/http's per-phase trace hooks. Bodyless requests therefore report a request-write time of zero.