Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: types refactor #40

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading