Skip to content

Commit

Permalink
Revert "Merge branch 'master' of https://github.com/traviscline/go-wrk
Browse files Browse the repository at this point in the history
…into traviscline-master"

This reverts commit aaeced0, reversing
changes made to 4aa05c1.
  • Loading branch information
roa committed May 17, 2013
1 parent aaeced0 commit 95c7318
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 94 deletions.
42 changes: 18 additions & 24 deletions bench.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,38 @@ package main

import (
"sync"
"time"
)

// type response represents the result of an HTTP request
type response struct {
code int
duration time.Duration
size int64
}

func bench() []byte {
work := make(chan struct{}, *totalCalls)
responses := make(chan response)
func bench(toCall string) []byte {
responseChannel := make(chan int, *totalCalls*2)
countChannel := make(chan bool, *totalCalls*2)
benchChannel := make(chan int64, *totalCalls*2)

benchTime := NewTimer()
benchTime.Reset()
//TODO check ulimit
wg := &sync.WaitGroup{}

for i := 0; i < *totalCalls; i++ {
work <- struct{}{}
}
close(work)
t1 := time.Now()
for i := 0; i < *numConnections; i++ {
go StartClient(
toCall,
*headers,
*method,
countChannel,
*disableKeepAlives,
*disableCompression,
work,
responses,
benchChannel,
responseChannel,
wg,
)
wg.Add(1)
}
go func() {
wg.Wait()
close(responses)
}()
return CalcStats(responses, t1)

wg.Wait()

result := CalcStats(
benchChannel,
responseChannel,
benchTime.Duration(),
)
return result
}
27 changes: 10 additions & 17 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,36 @@ package main

import (
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"sync"
"time"
)

func StartClient(u, h, m string, dka bool, dgzip bool, work chan struct{}, rc chan response, wg *sync.WaitGroup) {
func StartClient(u, h, m string, ch chan bool, dka bool, bc chan int64, rc chan int, wg *sync.WaitGroup) {
defer wg.Done()
tr := &http.Transport{DisableKeepAlives: dka, DisableCompression: dgzip}
req, err := http.NewRequest(m, u, nil)
if err != nil {
panic(err)
}
tr := &http.Transport{DisableKeepAlives: dka}
req, _ := http.NewRequest(m, u, nil)
sets := strings.Split(h, "\n")
for i := range sets {
split := strings.SplitN(sets[i], ":", 2)
if len(split) == 2 {
req.Header.Set(split[0], split[1])
}
}
timer := NewTimer()
for {
if _, ok := <-work; !ok {
return
}
t1 := time.Now()
timer.Reset()
resp, err := tr.RoundTrip(req)
if err != nil {
fmt.Println(err)
continue
}
size, err := io.Copy(ioutil.Discard, resp.Body)
if err != nil {
fmt.Println("error reading response:", err)
if len(ch) >= *totalCalls {
break
}
rc <- response{resp.StatusCode, time.Now().Sub(t1), size}
ch <- true
rc <- resp.StatusCode
bc <- timer.Duration()
resp.Body.Close()
}
}
7 changes: 6 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
{"Nodes":["ec2-46-137-41-179.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-127-42.eu-west-1.compute.amazonaws.com:7777","ec2-46-137-68-143.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-125-101.eu-west-1.compute.amazonaws.com:7777","ec2-79-125-65-101.eu-west-1.compute.amazonaws.com:7777","ec2-54-247-157-223.eu-west-1.compute.amazonaws.com:7777","ec2-54-216-37-26.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-124-20.eu-west-1.compute.amazonaws.com:7777","ec2-54-246-72-29.eu-west-1.compute.amazonaws.com:7777","ec2-46-51-144-122.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-153-122.eu-west-1.compute.amazonaws.com:7777","ec2-54-216-46-183.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-145-35.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-108-103.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-76-112.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-102-95.eu-west-1.compute.amazonaws.com:7777","ec2-54-228-24-121.eu-west-1.compute.amazonaws.com:7777","ec2-176-34-68-112.eu-west-1.compute.amazonaws.com:7777","ec2-46-137-50-124.eu-west-1.compute.amazonaws.com:7777","ec2-176-34-74-69.eu-west-1.compute.amazonaws.com:7777"],"Port":"7777"}
{
"Port" : "7777",
"Nodes" : [
"192.168.178.121:7777"
]
}
11 changes: 5 additions & 6 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

go build -o go-wrk *.go

while read node; do
echo $node
scp -i ~/Downloads/roa.pem go-wrk ubuntu@$node:
scp -i ~/Downloads/roa.pem config.json ubuntu@$node:
ssh -i ~/Downloads/roa.pem ubuntu@$node 'sudo su root -c "echo \"echo 88.198.77.76 app.adjust.io >> /etc/hosts\" | sudo bash"'
ssh -i ~/Downloads/roa.pem ubuntu@$node '/home/ubuntu/go-wrk -d s -f /home/ubuntu/config.json </dev/null >/home/ubuntu/err.log 2>&1 &' &
while read node
do
scp go-wrk root@$node:
scp config.json root@$node:
ssh root@$node '/root/go-wrk -d s -f /root/config.json </dev/null >/var/log/root-backup.log 2>&1 &'
done < node.txt
1 change: 0 additions & 1 deletion dist_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@ func rootHandler(w http.ResponseWriter, req *http.Request) {
*totalCalls, _ = strconv.Atoi(values.Get("n"))
*disableKeepAlives, _ = strconv.ParseBool(values.Get("k"))
toCall, _ := url.QueryUnescape(values.Get("url"))
fmt.Println("going to call:", toCall)
fmt.Fprintf(w, string(bench(toCall)))
}
21 changes: 10 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ type Config struct {
}

var (
numThreads = flag.Int("t", 1, "the numbers of threads used")
method = flag.String("m", "GET", "the http request method")
numConnections = flag.Int("c", 100, "the max numbers of connections used")
totalCalls = flag.Int("n", 1000, "the total number of calls processed")
disableKeepAlives = flag.Bool("k", true, "if keep-alives are disabled")
disableCompression = flag.Bool("z", true, "if compression (gzip) is disabled")
dist = flag.String("d", "", "dist mode")
configFile = flag.String("f", "", "json config file")
config Config
target string
headers = flag.String("H", "User-Agent: go-wrk 0.1 bechmark\nContent-Type: text/html", "the http headers sent separated by '\\n'")
numThreads = flag.Int("t", 1, "the numbers of threads used")
method = flag.String("m", "GET", "the http request method")
numConnections = flag.Int("c", 100, "the max numbers of connections used")
totalCalls = flag.Int("n", 1000, "the total number of calls processed")
disableKeepAlives = flag.Bool("k", true, "if keep-alives are disabled")
dist = flag.String("d", "", "dist mode")
configFile = flag.String("f", "", "json config file")
config Config
target string
headers = flag.String("H", "User-Agent: go-wrk 0.1 bechmark\nContent-Type: text/html;", "the http headers sent separated by '\\n'")
)

func init() {
Expand Down
1 change: 1 addition & 0 deletions master_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func runChild(distChan chan string, wg *sync.WaitGroup, node string) {
*disableKeepAlives,
url.QueryEscape(url.QueryEscape(target)),
)
fmt.Println(toCall)
resp, err := http.Get(toCall)
if err != nil {
fmt.Println(err)
Expand Down
2 changes: 1 addition & 1 deletion node.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ec2-54-246-40-186.eu-west-1.compute.amazonaws.com
192.168.178.121
68 changes: 35 additions & 33 deletions stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,60 @@ import (
"encoding/json"
"fmt"
"sort"
"time"
)

type Stats struct {
Url string
Connections int
Threads int
AvgDuration time.Duration
Duration time.Duration
Sum time.Duration
AvgDuration float64
Duration float64
Sum float64
Times []int
Transferred int64
Resp200 int64
Resp300 int64
Resp400 int64
Resp500 int64
}

func CalcStats(responseChannel chan response, startTime time.Time) []byte {
func CalcStats(benchChannel chan int64, responseChannel chan int, duration int64) []byte {
i := 0

stats := &Stats{
Url: target,
Connections: *numConnections,
Threads: *numThreads,
Times: make([]int, 0),
Times: make([]int, len(benchChannel)),
Duration: float64(duration),
AvgDuration: float64(duration),
}

for r := range responseChannel {
stats.Sum += r.duration
stats.Times = append(stats.Times, int(r.duration))
stats.Transferred += r.size
for rt := range benchChannel {
stats.Sum += float64(rt)
stats.Times[i] = int(rt)
i++
if len(benchChannel) == 0 {
break
}
}
sort.Ints(stats.Times)

for res := range responseChannel {
switch {
case r.code < 300:
case res < 300:
stats.Resp200++
case r.code < 400:
case res < 400:
stats.Resp300++
case r.code < 500:
case res < 500:
stats.Resp400++
case r.code < 600:
case res < 600:
stats.Resp500++
}
if len(responseChannel) == 0 {
break
}
}
// done ranging so requests are done
stats.Duration = time.Now().Sub(startTime)
if len(stats.Times) > 0 {
stats.AvgDuration = time.Duration(stats.Duration.Nanoseconds() / int64(len(stats.Times)))
}

PrintStats(stats)
b, err := json.Marshal(&stats)
if err != nil {
Expand All @@ -77,6 +83,7 @@ func CalcDistStats(distChan chan string) {
fmt.Println(err)
}
allStats.Duration += stats.Duration
allStats.Sum += stats.Sum
allStats.Times = append(allStats.Times, stats.Times...)
allStats.Resp200 += stats.Resp200
allStats.Resp300 += stats.Resp300
Expand All @@ -86,7 +93,7 @@ func CalcDistStats(distChan chan string) {
break
}
}
allStats.AvgDuration = time.Duration(allStats.Duration.Nanoseconds() / int64(statCount))
allStats.AvgDuration = allStats.Duration / float64(statCount)
PrintStats(allStats)
}

Expand All @@ -98,19 +105,14 @@ func PrintStats(allStats *Stats) {
fmt.Printf("URL:\t\t\t\t%s\n\n", allStats.Url)
fmt.Printf("Used Connections:\t\t%d\n", allStats.Connections)
fmt.Printf("Used Threads:\t\t\t%d\n", allStats.Threads)
fmt.Printf("Total number of calls:\t\t%d\n", totalInt)
fmt.Println("")
fmt.Printf("Total number of calls:\t\t%d\n\n", totalInt)
fmt.Println("============================TIMES============================")
fmt.Printf("Total time passed:\t\t%.2fs\n", allStats.Duration.Seconds())
fmt.Printf("Avg time per request:\t\t%.2fms\n", float64(allStats.Sum)/total/1e6)
fmt.Printf("Requests per second:\t\t%.2f\n", total/allStats.Duration.Seconds())
fmt.Printf("Median time per request:\t%.2fms\n", float64(allStats.Times[(totalInt-1)/2]/1e6))
fmt.Printf("99th percentile time:\t\t%.2fms\n", float64(allStats.Times[(totalInt/100*99)])/1e6)
fmt.Printf("Slowest time for request:\t%.2fms\n", float64(allStats.Times[totalInt-1]/1e6))
mb := float64(allStats.Transferred) / 1024 / 1024
fmt.Printf("Total Body bytes transferred:\t%.2fMB\n", mb)
fmt.Printf("Transfer rate:\t\t\t%.2fMB/s\n", mb/float64(allStats.Duration.Seconds()))
fmt.Println("")
fmt.Printf("Total time passed:\t\t%.2fs\n", allStats.AvgDuration/1E6)
fmt.Printf("Avg time per request:\t\t%.2fms\n", allStats.Sum/total/1000)
fmt.Printf("Requests per second:\t\t%.2f\n", total/(allStats.AvgDuration/1E6))
fmt.Printf("Median time per request:\t%.2fms\n", float64(allStats.Times[(totalInt-1)/2])/1000)
fmt.Printf("99th percentile time:\t\t%.2fms\n", float64(allStats.Times[(totalInt/100*99)])/1000)
fmt.Printf("Slowest time for request:\t%.2fms\n\n", float64(allStats.Times[totalInt-1]/1000))
fmt.Println("==========================RESPONSES==========================")
fmt.Printf("20X allStats.Responses:\t\t%d\t(%d%%)\n", allStats.Resp200, allStats.Resp200/totalInt*100)
fmt.Printf("30X allStats.Responses:\t\t%d\t(%d%%)\n", allStats.Resp300, allStats.Resp300/totalInt*100)
Expand Down
25 changes: 25 additions & 0 deletions timer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"time"
)

type Timer struct {
start time.Time
}

func NewTimer() *Timer {
timer := &Timer{}
return timer
}

func (timer *Timer) Reset() {
timer.start = time.Now().UTC()
}

func (timer *Timer) Duration() int64 {
now := time.Now().UTC()
nanos := now.Sub(timer.start).Nanoseconds()
micros := nanos / 1000
return micros
}

0 comments on commit 95c7318

Please sign in to comment.