Skip to content

Commit

Permalink
Merge pull request #40 from Azure/mchinta/runner
Browse files Browse the repository at this point in the history
*: types refactor
  • Loading branch information
fuweid authored Jan 11, 2024
2 parents 636d5a4 + e9cea86 commit f0bf5ad
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ result/
tmp/

#.txt files which contain response stats
.txt
*.txt
20 changes: 13 additions & 7 deletions api/types/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import "time"

// ResponseStats is the report about benchmark result.
type ResponseStats struct {
// List of failures
FailureList []error
// All the observed latencies
Latencies []float64
// total bytes read from apiserver
TotalReceivedBytes int64
}

type RunnerMetricReport struct {
// Total represents total number of requests.
Total int
// List of failures
FailureList []error
// Duration means the time of benchmark.
Duration time.Duration
// PercentileLatencies represents the latency distribution in seconds.
//
// NOTE: The key represents quantile.
PercentileLatencies map[float64]float64
// All the observed latencies
Latencies []float64
// total bytes read from apiserver
TotalReceivedBytes int64
// TODO:
// 1. Support failures partitioned by http code and verb
// 2. Support to dump all latency data
// PercentileLatencies represents the latency distribution in seconds.
PercentileLatencies [][2]float64 // [2]float64{percentile, value}
}
35 changes: 5 additions & 30 deletions cmd/kperf/commands/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"os"
"path/filepath"
"sort"

"github.com/Azure/kperf/api/types"
"github.com/Azure/kperf/request"
Expand Down Expand Up @@ -111,6 +110,8 @@ var runCommand = cli.Command{
}
defer f.Close()
}

//TODO: add printResponseStats for .json format
printResponseStats(f, stats)
return nil
},
Expand Down Expand Up @@ -151,33 +152,7 @@ func loadConfig(cliCtx *cli.Context) (*types.LoadProfile, error) {
return &profileCfg, nil
}

func printResponseStats(f *os.File, stats *types.ResponseStats) {
fmt.Fprint(f, "Response Stat: \n")
fmt.Fprintf(f, " Total: %v\n", stats.Total)

fmt.Fprintf(f, " Total Failures: %d\n", len(stats.FailureList))

for _, v := range stats.FailureList {
fmt.Fprintf(f, " %v\n", v)
}

fmt.Fprintf(f, " Observed Bytes: %v\n", stats.TotalReceivedBytes)

fmt.Fprintf(f, " Duration: %v\n", stats.Duration.String())

requestsPerSec := float64(stats.Total) / stats.Duration.Seconds()

fmt.Fprintf(f, " Requests/sec: %.2f\n", requestsPerSec)

fmt.Fprint(f, " Latency Distribution:\n")
keys := make([]float64, 0, len(stats.PercentileLatencies))
for q := range stats.PercentileLatencies {
keys = append(keys, q)
}

sort.Float64s(keys)

for _, q := range keys {
fmt.Fprintf(f, " [%.2f] %.3fs\n", q/100.0, stats.PercentileLatencies[q])
}
// TODO: Complete this function
func printResponseStats(f *os.File, stats *request.Result) {
fmt.Fprintf(f, "Response Stat: %v\n", stats)
}
35 changes: 9 additions & 26 deletions metrics/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package metrics

import (
"container/list"
"math"
"sort"
"sync"
"sync/atomic"

"github.com/Azure/kperf/api/types"
)

// ResponseMetric is a measurement related to http response.
Expand All @@ -17,7 +17,7 @@ type ResponseMetric interface {
// ObserveReceivedBytes observes the bytes read from apiserver.
ObserveReceivedBytes(bytes int64)
// Gather returns the summary.
Gather() (latencies []float64, percentileLatencies map[float64]float64, failureList []error, bytes int64)
Gather() types.ResponseStats
}

type responseMetricImpl struct {
Expand Down Expand Up @@ -55,9 +55,13 @@ func (m *responseMetricImpl) ObserveReceivedBytes(bytes int64) {
}

// Gather implements ResponseMetric.
func (m *responseMetricImpl) Gather() ([]float64, map[float64]float64, []error, int64) {
func (m *responseMetricImpl) Gather() types.ResponseStats {
latencies := m.dumpLatencies()
return latencies, buildPercentileLatencies(latencies), m.failureList, atomic.LoadInt64(&m.receivedBytes)
return types.ResponseStats{
FailureList: m.failureList,
Latencies: latencies,
TotalReceivedBytes: atomic.LoadInt64(&m.receivedBytes),
}
}

func (m *responseMetricImpl) dumpLatencies() []float64 {
Expand All @@ -69,24 +73,3 @@ func (m *responseMetricImpl) dumpLatencies() []float64 {
}
return res
}

var percentiles = []float64{0, 50, 90, 95, 99, 100}

func buildPercentileLatencies(latencies []float64) map[float64]float64 {
if len(latencies) == 0 {
return nil
}

res := make(map[float64]float64, len(percentiles))

n := len(latencies)
sort.Float64s(latencies)
for _, p := range percentiles {
idx := int(math.Ceil(float64(n) * p / 100))
if idx > 0 {
idx--
}
res[p] = latencies[idx]
}
return res
}
48 changes: 0 additions & 48 deletions metrics/request_test.go

This file was deleted.

23 changes: 15 additions & 8 deletions request/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,17 @@ import (

const defaultTimeout = 60 * time.Second

// Result contains responseStats vlaues from Gather() and adds Duration and Total values separately
type Result struct {
types.ResponseStats
// Duration means the time of benchmark.
Duration time.Duration
// Total means the total number of requests.
Total int
}

// Schedule files requests to apiserver based on LoadProfileSpec.
func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.Interface) (*types.ResponseStats, error) {
func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.Interface) (*Result, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

Expand Down Expand Up @@ -81,12 +90,10 @@ func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.I
wg.Wait()

totalDuration := time.Since(start)
_, percentileLatencies, failureList, bytes := respMetric.Gather()
return &types.ResponseStats{
Total: spec.Total,
FailureList: failureList,
Duration: totalDuration,
TotalReceivedBytes: bytes,
PercentileLatencies: percentileLatencies,
responseStats := respMetric.Gather()
return &Result{
ResponseStats: responseStats,
Duration: totalDuration,
Total: spec.Total,
}, nil
}

0 comments on commit f0bf5ad

Please sign in to comment.