gocannon

:boom: Performance-focused HTTP load testing tool written in Go

https://github.com/kffl/gocannon

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (14.5%) to scientific vocabulary

Keywords

benchmark benchmarking-utility gocannon golang http-load-testing load-testing performance

Keywords from Contributors

interactive mesh interpretability profiles sequences generic projection standardization optim embedded
Last synced: 6 months ago · JSON representation ·

Repository

:boom: Performance-focused HTTP load testing tool written in Go

Basic Info
  • Host: GitHub
  • Owner: kffl
  • License: apache-2.0
  • Language: Go
  • Default Branch: master
  • Homepage:
  • Size: 129 KB
Statistics
  • Stars: 78
  • Watchers: 5
  • Forks: 8
  • Open Issues: 8
  • Releases: 9
Topics
benchmark benchmarking-utility gocannon golang http-load-testing load-testing performance
Created over 4 years ago · Last pushed over 2 years ago
Metadata Files
Readme Contributing License Citation

README.md

:boom: gocannon - HTTP benchmarking tool

Gocannon Logo

CI Workflow Go Report Card GoDoc

Gocannon is a lightweight HTTP benchmarking tool, intended to measure changes in backend application performance over time. It keeps a detailed log of each request that is sent, not just the histogram of their latencies.

Installation

The easiest way to install Gocannon is to download pre-built binaries for your platform that are automatically attached to each release. If you wish to build Gocannon from source, clone this repository and run go build. Alternatively, you can run Gocannon as a container using jauderho/gocannon image.

Usage

``` usage: gocannon []

Flags: --help Show context-sensitive help (also try --help-long and --help-man). -d, --duration=10s Load test duration. -c, --connections=50 Maximum number of concurrent connections. --cpus Maximum number of logical CPUs that can be utilised. Defaults to the number of available CPU threads (or the GOMAXPROCS env variable). -t, --timeout=200ms HTTP client timeout. -m, --mode="reqlog" Statistics collection mode: reqlog (logs each request) or hist (stores histogram of completed requests latencies). -o, --output=file.csv File to save the request log in CSV format (reqlog mode) or a text file with raw histogram data (hist mode). -i, --interval=250ms Interval for statistics calculation (reqlog mode). --preallocate=1000 Number of requests in req log to preallocate memory for per connection (reqlog mode). --method=GET The HTTP request method (GET, POST, PUT, PATCH or DELETE). -b, --body="{data..." HTTP request body. -h, --header="k:v" ... HTTP request header(s). You can set more than one header by repeating this flag. --trust-all Omit SSL certificate validation. -f, --format=default Load test report format. Either 'default' (verbose), 'json' or 'yaml'. When json or yaml is specified, apart from the load test results, no additional info will be written to std out. --plugin=/to/p.so Plugin to run Gocannon with (path to .so file). --version Show application version.

Args: HTTP target URL with port (i.e. http://localhost:80/test or https://host:443/x) ```

Below is an example of a load test conducted using gocannon against an Express.js server (notice the performance improvement over time under sustained load):

```

gocannon http://localhost:3000/static -d 3s -c 50 Attacking http://localhost:3000/static with 50 connections over 3s gocannon goes brr... Total Req: 14990 Req/s: 4996.67 Interval stats: (interval = 250ms) |--REQS--| |------------------------LATENCY-------------------------| Count AVG P50 P75 P90 P99 673 18.004823ms 17.768106ms 18.810048ms 20.358396ms 31.970312ms 777 16.090895ms 16.096573ms 17.475942ms 18.049402ms 19.867212ms 922 13.630393ms 13.573315ms 14.279727ms 15.720507ms 17.725149ms 987 12.715278ms 12.050508ms 14.378844ms 15.661408ms 20.669683ms 1137 10.997768ms 10.201962ms 11.468307ms 13.736441ms 15.374815ms 1354 9.186035ms 8.689116ms 9.831591ms 10.417963ms 11.393158ms 1412 8.889394ms 8.444931ms 8.834144ms 10.480375ms 11.886929ms 1428 8.792173ms 7.880262ms 9.580714ms 10.753837ms 14.997604ms 1599 7.817586ms 7.578824ms 7.645575ms 9.083118ms 10.047772ms 1505 8.244456ms 7.580401ms 8.307621ms 9.611815ms 17.449891ms 1617 7.745439ms 7.422272ms 7.487905ms 9.132874ms 11.457255ms

1579 7.901125ms 7.525814ms 7.655212ms 9.577895ms 10.203331ms

 14990    9.986321ms  8.540818ms 11.252258ms 15.309979ms 19.632593ms

Responses by HTTP status code: 200 -> 14990 Requests ended with timeout/socket error: 1 ```

Saving request log to a CSV file

When used with the --output=filename.csv flag, raw request data (which includes the request HTTP code, starting timestamp, response timestamp both in nanoseconds since the beginning of the test as well as the ID of the connection which was used for that request) can be written into the specified csv file in the following format:

code;start;end;connection; 200;509761;30592963;0; 200;694043;34837869;0; 200;963463;36094909;0; 200;841397;37319812;0; [...]

In the CSV output file, the requests are sorted primarily by connection ID and secondarily by response timestamp (end column).

Preallocating memory for request log

Gocannon stores data of each completed request in a slice (one per each connection). If a given slice runs out of its initial capacity, the underlying array is re-allocated to a newly selected memory address with double the capacity. In order to minimize the performance impact of slice resizing during the load test, you can specify the number of requests in log per connection to preallocate memory for using the --preallocate flag.

Histogram mode

There are some use cases in which request log mode is not desirable. If you don't need a detailed log of each request that was completed during the load test, you can use histogram mode using the --mode=hist flag. When using histogram mode, upon each completed request, gocannon will only save its latency in a histogram (in a manner similar to how wrk or bombardier does that). That way, memory usage of the stats collector will remain constant over the entire duration of the load test. This results in gocannon having a total memory footprint of about 3MB when conducting a load test in histogram mode (when the timeout is set to a default 200ms).

Below is an example of a load test conducted with gocannon in histogram mode:

```

gocannon http://localhost:3000/static --duration=2m --mode=hist Attacking http://localhost:3000/static with 50 connections over 2m0s gocannon goes brr... Total Req: 13715707 Req/s: 114297.56 |------------------------LATENCY (μs)-----------------------| AVG P50 P75 P90 P99 436.45 278 508 925 2681 Responses by HTTP status code: 200 -> 13715707 ```

Similarly to saving CSV output in request log mode, you can write the histogram data to a text file using the --output=filename flag. The output contains the number of hits in each latency histogram bin (having width of 1μs) truncated up until the last non-zero value:

0 0 1 1 15 45 [...]

Custom plugins

Gocannon supports user-provided plugins, which can customize the requests sent during the load test. A custom plugin has to satisfy the GocannonPlugin interface defined in the common package, which also contains types required for plugin development. An example implementation with additional comments is provided in _example_plugin folder.

In order to build a plugin, use the following command inside its directory:

go build -buildmode=plugin -o plugin.so plugin.go

Once you obtain a shared object (.so) file, you can provide a path to it via --plugin flag. Bare in mind that a custom plugin .so file and the Gocannon binary using it must both be compiled using the same Go version.

Using Gocannon as a library

You can use Gocannon as a library for performing programmatic load tests. Consult GoDoc for API reference and main.go for example implementation. Please bare in mind that you cannot reuse a Gocannon instance to perform multiple load tests.

Load testing recommendations

  • Killing non-essential background processes: Since the activity of background processes running alongside the SUT may introduce anomalies in the obtained experiment results, it is advised to disable non-essential services for the load test duration. Additionally, when conducting a load test against a SUT running on the same machine as gocannon, you may want to assign the SUT and gocannon processes to separate sets of logical cores (i.e. via taskset) and update the GOMAXPROCS env variable accordingly (so as to reflect the number of cores available to gocannon).
  • Disabling Turbo Boost, EIST and ensuring a constant CPU clock: Changes of the CPU clock over the duration of the load test may introduce inconsistencies in the collected metrics, especially given that the detection of a suitable workload after the test start and subsequent increase of the CPU clock may cause observable improvement in application throughput shortly after the start of the load test. If your goal is to measure how the application performance changes over time under sustained load, you may want to disable Turbo Boost and EIST (or their equivalents in your system) as well as ensure that the CPU clock is not being reduced at idle (i.e. by setting the CPU mode to performance via the cpupower linux package).
  • Repeating the test runs: Performing multiple test runs improves the statistical significance of the obtained results and minimizes impact of potential one-off anomalies (i.e. background process activity during the load test) in the obtained data on the overall result. When combining data from multiple test runs, remember not to average the percentiles. Instead, place the obtained request latencies of all runs in a single dataset and calculate the desired percentiles on that dataset.

License

Copyright Paweł Kuffel 2021-2022, licensed under Apache 2.0 License.

The Gocannon logo contains the Go Gopher mascot which was originally designed by Renee French (http://reneefrench.blogspot.com/) and licensed under Creative Commons 3.0 Attributions license.

Owner

  • Name: Paweł Kuffel
  • Login: kffl
  • Kind: user
  • Location: Poland
  • Company: @FieldMaterials

Full-stack developer, distributed systems enthusiast.

Citation (CITATION.cff)

authors: 
  - family-names: Kuffel
    given-names: "Paweł"
cff-version: "1.1.0"
license: "Apache-2.0"
message: "Please use the following citation metadata."
repository-code: "https://github.com/kffl/gocannon"
title: "Gocannon - Performance-focused HTTP benchmarking tool"
version: "1.3.0"

GitHub Events

Total
  • Watch event: 7
Last Year
  • Watch event: 7

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 76
  • Total Committers: 4
  • Avg Commits per committer: 19.0
  • Development Distribution Score (DDS): 0.276
Past Year
  • Commits: 0
  • Committers: 0
  • Avg Commits per committer: 0.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Paweł Kuffel p****l@k****o 55
dependabot[bot] 4****] 17
Łukasz Grygier l****s@g****m 3
Jauder Ho j****o 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 9 months ago

All Time
  • Total issues: 17
  • Total pull requests: 69
  • Average time to close issues: 3 days
  • Average time to close pull requests: 28 days
  • Total issue authors: 4
  • Total pull request authors: 6
  • Average comments per issue: 0.35
  • Average comments per pull request: 0.43
  • Merged pull requests: 35
  • Bot issues: 0
  • Bot pull requests: 49
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • kffl (14)
  • DistributedMadlad (1)
  • jauderho (1)
  • hitzhangjie (1)
Pull Request Authors
  • dependabot[bot] (48)
  • kffl (16)
  • joy4eg (2)
  • TheCommonCold (1)
  • jauderho (1)
  • mjquinlan (1)
Top Labels
Issue Labels
feature (9) CI (3) to develop (3) documentation (2) bug (1) enhancement (1)
Pull Request Labels
dependencies (48) go (26) github_actions (22)

Packages

  • Total packages: 1
  • Total downloads: unknown
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 9
proxy.golang.org: github.com/kffl/gocannon
  • Versions: 9
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 7.0%
Average: 8.2%
Dependent repos count: 9.3%
Last synced: 7 months ago

Dependencies

.github/workflows/ci.yml actions
  • actions/checkout v3 composite
  • actions/setup-go v3 composite
.github/workflows/release.yml actions
  • actions/checkout v3 composite
  • wangyoucao577/go-release-action v1.28 composite
go.mod go
  • github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
  • github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15
  • github.com/kr/pretty v0.1.0
  • github.com/stretchr/testify v1.8.0
  • github.com/valyala/fasthttp v1.39.0
  • gopkg.in/alecthomas/kingpin.v2 v2.2.6
  • gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
  • gopkg.in/yaml.v2 v2.4.0
go.sum go
  • github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
  • github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15
  • github.com/andybalholm/brotli v1.0.4
  • github.com/davecgh/go-spew v1.1.0
  • github.com/davecgh/go-spew v1.1.1
  • github.com/klauspost/compress v1.15.0
  • github.com/kr/pretty v0.1.0
  • github.com/kr/pty v1.1.1
  • github.com/kr/text v0.1.0
  • github.com/pmezard/go-difflib v1.0.0
  • github.com/stretchr/objx v0.1.0
  • github.com/stretchr/objx v0.4.0
  • github.com/stretchr/testify v1.4.0
  • github.com/stretchr/testify v1.7.1
  • github.com/stretchr/testify v1.8.0
  • github.com/valyala/bytebufferpool v1.0.0
  • github.com/valyala/fasthttp v1.39.0
  • github.com/valyala/tcplisten v1.0.0
  • golang.org/x/crypto v0.0.0-20220214200702-86341886e292
  • golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
  • golang.org/x/net v0.0.0-20220225172249-27dd8689420f
  • golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
  • golang.org/x/sys v0.0.0-20210423082822-04245dca01da
  • golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
  • golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
  • golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9
  • golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
  • golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
  • golang.org/x/text v0.3.6
  • golang.org/x/text v0.3.7
  • golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
  • gopkg.in/alecthomas/kingpin.v2 v2.2.6
  • gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
  • gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
  • gopkg.in/yaml.v2 v2.2.2
  • gopkg.in/yaml.v2 v2.4.0
  • gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
  • gopkg.in/yaml.v3 v3.0.1