Skip to content

Commit

Permalink
Add Request Duration+BPS+TTFB percentiles (#219)
Browse files Browse the repository at this point in the history
Add Request Duration+BPS+TTFB percentiles to JSON output.

Written with `--json` parameter on output.
  • Loading branch information
klauspost authored Jun 30, 2022
1 parent bf0c376 commit a8e4c64
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
12 changes: 12 additions & 0 deletions pkg/aggregate/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type SingleSizedRequests struct {
FastestMillis int `json:"fastest_millis"`
// Slowest request time.
SlowestMillis int `json:"slowest_millis"`
// DurPct is duration percentiles.
DurPct [101]int `json:"dur_percentiles_millis"`
// Time to first byte if applicable.
FirstByte *TTFB `json:"first_byte,omitempty"`
// FirstAccess is filled if the same object is accessed multiple times.
Expand All @@ -68,6 +70,10 @@ func (a *SingleSizedRequests) fill(ops bench.Operations) {
a.SlowestMillis = durToMillis(ops.Median(1).Duration())
a.FastestMillis = durToMillis(ops.Median(0).Duration())
a.FirstByte = TtfbFromBench(ops.TTFB(start, end))
for i := range a.DurPct[:] {
a.DurPct[i] = durToMillis(ops.Median(float64(i) / 100).Duration())
}

}

func (a *SingleSizedRequests) fillFirstLast(ops bench.Operations) {
Expand Down Expand Up @@ -104,6 +110,9 @@ type RequestSizeRange struct {
BpsFastest float64 `json:"bps_fastest"`
BpsSlowest float64 `json:"bps_slowest"`

// BpsPct is BPS percentiles.
BpsPct [101]float64 `json:"bps_percentiles"`

// FirstAccess is filled if the same object is accessed multiple times.
// This records the first touch of the object.
FirstAccess *RequestSizeRange `json:"first_access,omitempty"`
Expand All @@ -126,6 +135,9 @@ func (r *RequestSizeRange) fill(s bench.SizeSegment) {
r.Bps99 = s.Ops.Median(0.99).BytesPerSec().Float()
r.BpsFastest = s.Ops.Median(0.0).BytesPerSec().Float()
r.BpsSlowest = s.Ops.Median(1).BytesPerSec().Float()
for i := range r.BpsPct[:] {
r.BpsPct[i] = s.Ops.Median(float64(i) / 100).BytesPerSec().Float()
}
}

func (r *RequestSizeRange) fillFirst(s bench.SizeSegment) {
Expand Down
23 changes: 14 additions & 9 deletions pkg/aggregate/ttfb.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ import (

// TTFB contains times to first byte if applicable.
type TTFB struct {
AverageMillis int `json:"average_millis"`
FastestMillis int `json:"fastest_millis"`
P25Millis int `json:"p25_millis"`
MedianMillis int `json:"median_millis"`
P75Millis int `json:"p75_millis"`
P90Millis int `json:"p90_millis"`
P99Millis int `json:"p99_millis"`
SlowestMillis int `json:"slowest_millis"`
AverageMillis int `json:"average_millis"`
FastestMillis int `json:"fastest_millis"`
P25Millis int `json:"p25_millis"`
MedianMillis int `json:"median_millis"`
P75Millis int `json:"p75_millis"`
P90Millis int `json:"p90_millis"`
P99Millis int `json:"p99_millis"`
SlowestMillis int `json:"slowest_millis"`
PercentilesMillis [101]int `json:"percentiles_millis"`
}

// String returns a human printable version of the time to first byte.
Expand All @@ -57,7 +58,7 @@ func TtfbFromBench(t bench.TTFB) *TTFB {
if t.Average <= 0 {
return nil
}
return &TTFB{
t2 := TTFB{
AverageMillis: durToMillis(t.Average),
SlowestMillis: durToMillis(t.Worst),
P25Millis: durToMillis(t.P25),
Expand All @@ -67,4 +68,8 @@ func TtfbFromBench(t bench.TTFB) *TTFB {
P99Millis: durToMillis(t.P99),
FastestMillis: durToMillis(t.Best),
}
for i, v := range t.Percentiles[:] {
t2.PercentilesMillis[i] = durToMillis(v)
}
return &t2
}
21 changes: 13 additions & 8 deletions pkg/bench/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ type Segment struct {

// TTFB contains time to first byte stats.
type TTFB struct {
Average time.Duration
Best time.Duration
P25 time.Duration
Median time.Duration
P75 time.Duration
P90 time.Duration
P99 time.Duration
Worst time.Duration
Average time.Duration
Best time.Duration
P25 time.Duration
Median time.Duration
P75 time.Duration
P90 time.Duration
P99 time.Duration
Worst time.Duration
Percentiles [101]time.Duration `json:"percentiles_millis"`
}

// Segments is a slice of segment elements.
Expand Down Expand Up @@ -111,6 +112,10 @@ func (o Operations) TTFB(start, end time.Time) TTFB {
P99: filtered.Median(0.99).TTFB(),
Worst: filtered.Median(1).TTFB(),
}
for i := range res.Percentiles[:] {
res.Percentiles[i] = filtered.Median(float64(i) / 100).TTFB()
}

for _, op := range filtered {
ttfb := op.TTFB()
res.Average += ttfb
Expand Down

0 comments on commit a8e4c64

Please sign in to comment.