Skip to content

Commit

Permalink
Improve splitting by operation speed (#277)
Browse files Browse the repository at this point in the history
Use non-copying splitting for faster compare and merging.

Add error comparison
  • Loading branch information
klauspost authored Jul 14, 2023
1 parent 560cb38 commit 77be8b7
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 12 deletions.
14 changes: 9 additions & 5 deletions cli/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ func printCompare(ctx *cli.Context, before, after bench.Operations) {
start, end := ops.ActiveTimeRange(!isMultiOp)
return end.Sub(start).Round(time.Second)
}

for _, typ := range before.OpTypes() {
afterOps := after.SortSplitByOpType()
for typ, before := range before.SortSplitByOpType() {
if wantOp := ctx.String("analyze.op"); wantOp != "" {
if wantOp != typ {
continue
}
}
before := before.FilterByOp(typ)
after := after.FilterByOp(typ)

after := afterOps[typ]
console.Println("-------------------")
console.SetColor("Print", color.New(color.FgHiWhite))
console.Println("Operation:", typ)
Expand All @@ -117,7 +117,11 @@ func printCompare(ctx *cli.Context, before, after bench.Operations) {
console.Println(err)
continue
}

if bErrs, aErrs := before.NErrors(), after.NErrors(); bErrs+aErrs > 0 {
console.SetColor("Print", color.New(color.FgHiRed))
console.Println("Errors:", bErrs, "->", aErrs)
console.SetColor("Print", color.New(color.FgWhite))
}
if len(before) != len(after) {
console.Println("Operations:", len(before), "->", len(after))
}
Expand Down
2 changes: 1 addition & 1 deletion cli/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func mainMerge(ctx *cli.Context) error {
}()
}
}
for typ, ops := range allOps.ByOp() {
for typ, ops := range allOps.SortSplitByOpType() {
start, end := ops.ActiveTimeRange(true)
if !start.Before(end) {
console.Errorf("Type %v contains no overlapping items", typ)
Expand Down
2 changes: 1 addition & 1 deletion pkg/bench/analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestOperations_Segment(t *testing.T) {
if err != nil {
t.Fatal(err)
}
for typ, ops := range ops.ByOp() {
for typ, ops := range ops.SortSplitByOpType() {
segs := ops.Segment(SegmentOptions{
From: time.Time{},
PerSegDuration: time.Second,
Expand Down
54 changes: 49 additions & 5 deletions pkg/bench/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,25 @@ func (o Operations) SortByEndpoint() {
})
}

// SortByOpType will sort the operations by operation type.
// Earliest operations first.
func (o Operations) SortByOpType() {
if sort.SliceIsSorted(o, func(i, j int) bool {
if o[i].OpType == o[j].OpType {
return o[i].Start.Before(o[j].Start)
}
return o[i].OpType < o[j].OpType
}) {
return
}
sort.Slice(o, func(i, j int) bool {
if o[i].OpType == o[j].OpType {
return o[i].Start.Before(o[j].Start)
}
return o[i].OpType < o[j].OpType
})
}

// SortByDuration will sort the operations by duration taken to complete.
// Fastest operations first.
func (o Operations) SortByDuration() {
Expand Down Expand Up @@ -347,12 +366,26 @@ func (o Operations) SortSplitByEndpoint() map[string]Operations {
return dst
}

// ByOp separates the operations by op.
func (o Operations) ByOp() map[string]Operations {
dst := make(map[string]Operations, 1)
for _, o := range o {
dst[o.OpType] = append(dst[o.OpType], o)
// SortSplitByOpType will sort operations by op + start time and split by op.
func (o Operations) SortSplitByOpType() map[string]Operations {
o.SortByOpType()
dst := make(map[string]Operations, 5)
lastOp := ""
start := 0
for i, op := range o {
if op.OpType == lastOp {
continue
}
if lastOp != "" {
dst[lastOp] = o[start:i]
}
lastOp = op.OpType
start = i
}
if lastOp != "" {
dst[lastOp] = o[start:]
}

return dst
}

Expand Down Expand Up @@ -829,6 +862,17 @@ func (o Operations) Errors() []string {
return errs
}

// NErrors returns the number of errors found.
func (o Operations) NErrors() int {
var n int
for _, op := range o {
if len(op.Err) != 0 {
n++
}
}
return n
}

// FilterSuccessful returns the successful requests.
func (o Operations) FilterSuccessful() Operations {
if len(o) == 0 {
Expand Down

0 comments on commit 77be8b7

Please sign in to comment.