diff --git a/baton.go b/baton.go index 55eaef1..ee65323 100644 --- a/baton.go +++ b/baton.go @@ -23,6 +23,7 @@ import ( "github.com/valyala/fasthttp" "io/ioutil" "log" + "math" "time" ) @@ -148,12 +149,11 @@ func processResults(baton *Baton, preparedRunConfiguration runConfiguration) { baton.result.httpResult.status3xxCount += result.status3xxCount baton.result.httpResult.status4xxCount += result.status4xxCount baton.result.httpResult.status5xxCount += result.status5xxCount - if result.minTime < baton.result.httpResult.minTime { - baton.result.minTime = result.minTime - } - if result.maxTime > baton.result.httpResult.maxTime { - baton.result.maxTime = result.maxTime + + for b := 0; b < len(result.responseTimes); b++ { + baton.result.httpResult.responseTimes = append(baton.result.httpResult.responseTimes, result.responseTimes[b]) } + timeSum += result.timeSum requestCount += result.totalSuccess } @@ -161,6 +161,46 @@ func processResults(baton *Baton, preparedRunConfiguration runConfiguration) { baton.result.averageTime = float32(timeSum) / float32(requestCount) baton.result.totalRequests = baton.result.httpResult.total() baton.result.requestsPerSecond = int(float64(baton.result.totalRequests)/baton.result.timeTaken.Seconds() + 0.5) + + //Find new min and max + min := math.MaxInt64 + max := 0 + for b := 0; b < len(baton.result.httpResult.responseTimes); b++ { + if baton.result.httpResult.responseTimes[b] < min { + min = baton.result.httpResult.responseTimes[b] + } + if baton.result.httpResult.responseTimes[b] > max { + max = baton.result.httpResult.responseTimes[b] + } + } + baton.result.minTime = min + baton.result.maxTime = max + + //Find brackets + var numOfBrackets = 10 + rtCounts := make([][3]int, numOfBrackets) + bs := (max - min) / numOfBrackets + if bs < 1 { + bs = 1 + } + for i := 0; i < numOfBrackets; i++ { + if min+(bs*(i+1)) < max { + rtCounts[i][0] = min + (bs * (i + 1)) + } + } + rtCounts[numOfBrackets-1][0] = max + + for b := 0; b < len(baton.result.httpResult.responseTimes); b++ { + for i := 0; i < numOfBrackets; i++ { + if baton.result.httpResult.responseTimes[b] <= rtCounts[i][0] { + rtCounts[i][1] += 1 + rtCounts[i][2] = int((float64(rtCounts[i][1]) / float64(len(baton.result.httpResult.responseTimes))) * 100) + } + } + } + + baton.result.httpResult.responseTimesPercent = rtCounts + } func configureLogging(suppressOutput bool) { diff --git a/http_result.go b/http_result.go index fd0c0d1..d33d22d 100644 --- a/http_result.go +++ b/http_result.go @@ -30,10 +30,12 @@ type HTTPResult struct { minTime int timeSum int64 totalSuccess int + responseTimes []int + responseTimesPercent [][3]int } func newHTTPResult() *HTTPResult { - return &HTTPResult{0, 0, 0, 0, 0, 0, 0, math.MaxInt64, 0, 0} + return &HTTPResult{0, 0, 0, 0, 0, 0, 0, math.MaxInt64, 0, 0, make([]int, 0), make([][3]int, 0)} } func (httpResult HTTPResult) total() int { diff --git a/result.go b/result.go index c2d994e..e521493 100644 --- a/result.go +++ b/result.go @@ -39,8 +39,8 @@ func newResult() *Result { func (result *Result) printResults() { fmt.Println() + fmt.Printf("=========================== Results ========================================\n") fmt.Println() - fmt.Printf("====================== Results ======================\n") fmt.Printf("Total requests: %10d\n", result.totalRequests) fmt.Printf("Time taken to complete requests: %15s\n", result.timeTaken.String()) fmt.Printf("Requests per second: %10d\n", result.requestsPerSecond) @@ -49,12 +49,26 @@ func (result *Result) printResults() { fmt.Printf("Min response time (ms): %10d\n", result.minTime) fmt.Printf("Avg response time (ms): %6.2f\n", result.averageTime) } - fmt.Printf("===================== Breakdown =====================\n") + fmt.Println() + fmt.Printf("========= Percentage of responses by status code ==========================\n") + fmt.Println() fmt.Printf("Number of connection errors: %10d\n", result.httpResult.connectionErrorCount) fmt.Printf("Number of 1xx responses: %10d\n", result.httpResult.status1xxCount) fmt.Printf("Number of 2xx responses: %10d\n", result.httpResult.status2xxCount) fmt.Printf("Number of 3xx responses: %10d\n", result.httpResult.status3xxCount) fmt.Printf("Number of 4xx responses: %10d\n", result.httpResult.status4xxCount) fmt.Printf("Number of 5xx responses: %10d\n", result.httpResult.status5xxCount) - fmt.Printf("=====================================================\n") + fmt.Println() + fmt.Printf("========= Percentage of responses received within a certain time (ms)======\n") + fmt.Println() + + for i := 0; i < len(result.httpResult.responseTimesPercent); i++ { + if result.httpResult.responseTimesPercent[i][0] > 0 { + fmt.Printf("%10d%% : %d ms\n", result.httpResult.responseTimesPercent[i][2], result.httpResult.responseTimesPercent[i][0]) + } + } + fmt.Println() + + fmt.Printf("===========================================================================\n") + } diff --git a/worker.go b/worker.go index 5509990..9da9d82 100644 --- a/worker.go +++ b/worker.go @@ -114,18 +114,24 @@ func (worker *worker) collectStatistics(timings chan int) { sum, total := int64(0), 0 for timing := range timings { - timing = timing / 1000 + //Nano to milli + timing = timing / 1000000 // The first request is associated with overhead // in setting up the client so we ignore it's result if first { first = false continue } + if timing < worker.httpResult.minTime { worker.httpResult.minTime = timing } else if timing >= worker.httpResult.maxTime { worker.httpResult.maxTime = timing } + + //save all response times to compute results later + worker.httpResult.responseTimes = append(worker.httpResult.responseTimes, timing) + sum += int64(timing) total++ }