Skip to content

Instantly share code, notes, and snippets.

@rattrap
Created May 13, 2018 00:21
Show Gist options
  • Save rattrap/65847600ef10dea798a1d140e9c5330f to your computer and use it in GitHub Desktop.
Save rattrap/65847600ef10dea798a1d140e9c5330f to your computer and use it in GitHub Desktop.
HTTP benchmark tool in golang
package main
import (
"fmt"
"net/http"
"os"
"strconv"
"time"
)
func main() {
args := os.Args
if len(args) < 4 {
panic("usage: bench <url> <requests> <concurrency>")
}
url := os.Args[1]
requests, err := strconv.Atoi(os.Args[2])
if err != nil {
panic("invalid number of requests")
}
concurrency, err := strconv.Atoi(os.Args[3])
if err != nil {
panic("invalid number of concurrent users")
}
failed, averageResponseTime := bench(url, requests, concurrency)
total := requests * concurrency
fmt.Println("Completed", total-failed, "of", total, "requests")
fmt.Println("Average response time", averageResponseTime)
}
func bench(url string, requests int, concurrency int) (failed int, average time.Duration) {
chanFailed := make(chan int)
chanAverage := make(chan time.Duration)
for c := 1; c <= concurrency; c++ {
go func(c int) {
for r := 1; r <= requests; r++ {
start := time.Now()
status := doRequest(url, c)
if status == 200 {
chanFailed <- 0
} else {
chanFailed <- 1
}
elapsed := time.Now().Sub(start)
chanAverage <- elapsed
}
}(c)
}
for c := 1; c <= concurrency; c++ {
for r := 1; r <= requests; r++ {
f := <-chanFailed
if f == 1 {
failed++
}
average += <-chanAverage
}
}
average = average / time.Duration(requests*concurrency)
return failed, average
}
func doRequest(url string, concurrency int) int {
client := http.Client{
Timeout: time.Second * 2,
}
req, _ := http.NewRequest(http.MethodGet, url, nil)
req.Header.Set("User-Agent", "perf-test-"+strconv.Itoa(concurrency))
res, _ := client.Do(req)
if res == nil {
return 500
}
return res.StatusCode
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment