There are a million load testers that already exist across the internet - here are a few that I like:
hey
- A pretty simple CLI tool for generating basic requests: https://github.com/rakyll/hey
minigun
- Another option with better metrics publishing: https://github.com/wayfair-incubator/minigun
vegeta
- Yet another option... (etc etc,): https://github.com/tsenart/vegeta
Conceptually, they all do the same thing: Give them a descriptor of a request that you'd like the tool to send along with various rate options, and the tool sends that request at the given rate.
Functionally, they all do it differently: they use distinct http libraries, have their own unique command line options, and generate their post-run reports in various formats. If you're looking to adopt one of these tools for your team, that's a lot to learn and evaluate!
What if there was a tool that used request descriptors that you already had? Like with curl
?
That's where I thought spam
could generate some value. My team frequently needed to perform load
tests for new feature releases, and to do it, had to translate curl
requests from their
REST Clients into the right flavor of CLI options for an off-the-shelf load test utility.
spam
is a tool I built that's so simple, it's almost ridiculous.
It takes in any valid command line program, and runs that command at a set rate. Here's what that
looks like to send 10 req/s to www.google.com:
spam -r 10 -- curl www.google.com
The cognitive overhead here is nearly zero since it uses existing http request tooling like curl
to handle the http request rather than baking that into spam
itself. As a challenge, let's
look at other load test tooling and format a valid 10req/s load test in hey
, minigun
, or vegeta
:
# Hey
hey -n 10 -m GET www.google.com
# Minigun
minigun -fire-target http://www.google.com -send-method GET -fire-rate 10
# Vegeta
echo "GET http://www.google.com/" | vegeta attack -rate 10
None of them are ridiculously complex for a simple request -- but what if we needed to send this one? (exported in a single click from my REST client of choice, Insomnia)
curl --request POST \
--url https://www.google.com/ \
--header 'Authorization: Bearer SuperSecretToken' \
--header 'Content-Type: application/json' \
--header 'Made-Up-Header: made-up-value' \
--data '{
"hello": "world"
}'
Each tool has different options for HTTPS, Headers, Request Bodies, Content Types, Authorization -- it's
no longer as easy to piece it together! With spam
, though, you can turn it into a load test the exact
same way as we did with the simple request above:
spam -r 10 -- curl --request POST \
--url https://www.google.com/ \
--header 'Authorization: Bearer SuperSecretToken' \
--header 'Content-Type: application/json' \
--header 'Made-Up-Header: made-up-value' \
--data '{
"hello": "world"
}'
It's a breath of fresh air to not worry about request complexity when scaling up the volume on a request you've already built.
Now that we've established that spam
can do the same thing as complicated tools for simple cases,
what about the bonus features those tools provide like timeouts, load test durations, or reporting?
It turns out most of that can be done with other composed cli utilities!
curl
supports request timeouts with (--max-time
and --fail
), so spam does too:
# 10 req/s, timeout after 100ms
spam -r 10 -- curl --max-time 0.100 --fail www.google.com
The nice part about composing this utility with curl
is that spam
gets all of its features for free.
If you don't use curl
, you can also substitute whatever http request cli that you wish.
note: spam
doesn't currently report failure status codes, but it does track it internally. If you have ideas
for how to represent this in its output, feel free to open an issue or shoot me a message.
timeout
is a GNU coreutil that will end a given command after a given time, so we don't need a duration option:
timeout 10s spam -r 10 -- curl www.google.com
Even though it's already handled by timeout
, I can imagine spam
adding this feature in the future
to eliminate the dependency. In the meantime, it's excellent that a built-in feature isn't necessary.
spam
outputs program execution times in milliseconds to standard out. For example:
> timeout 10s spam -- curl www.google.com
135
155
139
150
150
140
147
153
142
This data can be redirected to a file and imported into tools like excel / google sheets, or directly
plotted by piping it to another command line tool like asciigraph
:
timeout 10s spam -- curl www.google.com | asciigraph -r -h 10 -w 40
outputs:
For my use cases, I don't need my console to output request percentiles in favor of using in-app telemetry,
but since spam
outputs the raw data, the sky's the limit for what kind of post analysis can be performed.
spam
is probably the most useful utility I've ever built, even though it's practically just a loop!
It's dead simple and can be combined with other command line tooling to achieve a wide range of outcomes
without a complex/custom API.
The utility is currently published as a Homebrew Tap if you're a mac user interested in trying it out:
brew tap Steven-Ireland/homebrew-tap
brew install spam
If you're on linux, download the latest release binary from here and install wherever it's convenient.
If you just want to browse the code, it's available here: https://github.com/Steven-Ireland/spam
Thanks for reading, and good luck spamming your APIs!