From e44d3abc775efbef6a53e6a540b0bd818297658e Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Tue, 10 Jan 2017 18:15:53 -0800 Subject: [PATCH] pkg/report: support 99.9-percentile, change column name --- pkg/report/report.go | 22 +++++++++++++++------- pkg/report/report_test.go | 33 +++++++++++++++++++++++++++++++++ pkg/report/timeseries.go | 2 +- 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 pkg/report/report_test.go diff --git a/pkg/report/report.go b/pkg/report/report.go index ea4d17695..bf8b47730 100644 --- a/pkg/report/report.go +++ b/pkg/report/report.go @@ -99,7 +99,7 @@ func (r *report) String() (s string) { s += fmt.Sprintf(" Stddev:\t%s.\n", r.sec2str(r.stddev)) s += fmt.Sprintf(" Requests/sec:\t"+r.precision+"\n", r.rps) s += r.histogram() - s += r.latencies() + s += r.sprintLatencies() if r.sps != nil { s += fmt.Sprintf("%v\n", r.sps.getTimeSeries()) } @@ -156,17 +156,25 @@ func (r *report) processResults() { } } -func (r *report) latencies() string { - pctls := []int{10, 25, 50, 75, 90, 95, 99} - data := make([]float64, len(pctls)) +var pctls = []float64{10, 25, 50, 75, 90, 95, 99, 99.9} + +// percentiles returns percentile distribution of float64 slice. +func percentiles(nums []float64) (data []float64) { + data = make([]float64, len(pctls)) j := 0 - for i := 0; i < len(r.lats) && j < len(pctls); i++ { - current := i * 100 / len(r.lats) + n := len(nums) + for i := 0; i < n && j < len(pctls); i++ { + current := float64(i) * 100.0 / float64(n) if current >= pctls[j] { - data[j] = r.lats[i] + data[j] = nums[i] j++ } } + return +} + +func (r *report) sprintLatencies() string { + data := percentiles(r.lats) s := fmt.Sprintf("\nLatency distribution:\n") for i := 0; i < len(pctls); i++ { if data[i] > 0 { diff --git a/pkg/report/report_test.go b/pkg/report/report_test.go new file mode 100644 index 000000000..a77c1a68d --- /dev/null +++ b/pkg/report/report_test.go @@ -0,0 +1,33 @@ +// Copyright 2017 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package report + +import "testing" + +func TestPercentiles(t *testing.T) { + nums := make([]float64, 100) + nums[99] = 1 // 99-percentile (1 out of 100) + data := percentiles(nums) + if data[len(pctls)-2] != 1 { + t.Fatalf("99-percentile expected 1, got %f", data[len(pctls)-2]) + } + + nums = make([]float64, 1000) + nums[999] = 1 // 99.9-percentile (1 out of 1000) + data = percentiles(nums) + if data[len(pctls)-1] != 1 { + t.Fatalf("99.9-percentile expected 1, got %f", data[len(pctls)-1]) + } +} diff --git a/pkg/report/timeseries.go b/pkg/report/timeseries.go index 0cabb2339..76c194911 100644 --- a/pkg/report/timeseries.go +++ b/pkg/report/timeseries.go @@ -111,7 +111,7 @@ func (sp *secondPoints) getTimeSeries() TimeSeries { func (ts TimeSeries) String() string { buf := new(bytes.Buffer) wr := csv.NewWriter(buf) - if err := wr.Write([]string{"unix_ts", "avg_latency", "throughput"}); err != nil { + if err := wr.Write([]string{"UNIX-TS", "AVG-LATENCY-MS", "AVG-THROUGHPUT"}); err != nil { log.Fatal(err) } rows := [][]string{}