Skip to content

Commit

Permalink
Any filter optimization (#7205)
Browse files Browse the repository at this point in the history
* first attempt at any filter optimization

Signed-off-by: Calum Murray <cmurray@redhat.com>

* fixed logic in any filter optimizer

Signed-off-by: Calum Murray <cmurray@redhat.com>

* Optimized further

Signed-off-by: Calum Murray <cmurray@redhat.com>

* Updated cleanup methods

Signed-off-by: Calum Murray <cmurray@redhat.com>

* updated one more reference of Done to Cleanup

Signed-off-by: Calum Murray <cmurray@redhat.com>

* Apply fixes from all filter PR review

Signed-off-by: Calum Murray <cmurray@redhat.com>

---------

Signed-off-by: Calum Murray <cmurray@redhat.com>
  • Loading branch information
Cali0707 authored Sep 29, 2023
1 parent 3dfc2ea commit 3b1465a
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 88 deletions.
67 changes: 34 additions & 33 deletions pkg/eventfilter/benchmarks/all_filter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"
"knative.dev/eventing/pkg/eventfilter"
"knative.dev/eventing/pkg/eventfilter/subscriptionsapi"
Expand Down Expand Up @@ -56,59 +57,59 @@ func BenchmarkAllFilter(b *testing.B) {
return subscriptionsapi.NewAllFilter(filters...)
},
FilterBenchmark{
name: "All filter with exact filter test",
arg: []eventfilter.Filter{filter},
event: event,
name: "All filter with exact filter test",
arg: []eventfilter.Filter{filter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter match all subfilters",
arg: []eventfilter.Filter{filter, prefixFilter, suffixFilter},
event: event,
name: "All filter match all subfilters",
arg: []eventfilter.Filter{filter, prefixFilter, suffixFilter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter no 1 match at end of array",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch, filter},
event: event,
name: "All filter no 1 match at end of array",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch, filter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter no 1 match at start of array",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, suffixFilterNoMatch},
event: event,
name: "All filter no 1 match at start of array",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, suffixFilterNoMatch},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with multiple exact filters that match",
arg: []eventfilter.Filter{filter, exactFilter2, exactFilter3},
event: event,
name: "All filter with multiple exact filters that match",
arg: []eventfilter.Filter{filter, exactFilter2, exactFilter3},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with one non-matching filter in the middle",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, exactFilter2},
event: event,
name: "All filter with one non-matching filter in the middle",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, exactFilter2},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with one non-matching filter at the end",
arg: []eventfilter.Filter{filter, exactFilter2, prefixFilterNoMatch},
event: event,
name: "All filter with all non-matching filters",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with all non-matching filters",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch},
event: event,
name: "All filter with one non-matching filter at the end",
arg: []eventfilter.Filter{filter, exactFilter2, prefixFilterNoMatch},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with large number of sub-filters that match",
arg: largeMatchingFilters,
event: event,
name: "All filter with large number of sub-filters that match",
arg: largeMatchingFilters,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with large number of sub-filters that do not match",
arg: largeNonMatchingFilters,
event: event,
name: "All filter with large number of sub-filters that do not match",
arg: largeNonMatchingFilters,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "All filter with alternating matching and non-matching filters",
arg: alternatingFilters,
event: event,
name: "All filter with alternating matching and non-matching filters",
arg: alternatingFilters,
events: []cloudevents.Event{event},
},
)

Expand Down
37 changes: 25 additions & 12 deletions pkg/eventfilter/benchmarks/any_filter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"
"knative.dev/eventing/pkg/eventfilter"
"knative.dev/eventing/pkg/eventfilter/subscriptionsapi"
Expand All @@ -27,6 +28,8 @@ import (
func BenchmarkAnyFilter(b *testing.B) {
// Full event with all possible fields filled
event := cetest.FullEvent()
otherEvent := cetest.FullEvent()
otherEvent.SetType("qwertyuiop")

filter, _ := subscriptionsapi.NewExactFilter(map[string]string{"id": event.ID()})
prefixFilter, _ := subscriptionsapi.NewPrefixFilter(map[string]string{"type": event.Type()[0:5]})
Expand All @@ -40,24 +43,34 @@ func BenchmarkAnyFilter(b *testing.B) {
return subscriptionsapi.NewAnyFilter(filters...)
},
FilterBenchmark{
name: "Any filter with exact filter test",
arg: []eventfilter.Filter{filter},
event: event,
name: "Any filter with exact filter test",
arg: []eventfilter.Filter{filter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Any filter match all subfilters",
arg: []eventfilter.Filter{filter, prefixFilter, suffixFilter},
event: event,
name: "Any filter match all subfilters",
arg: []eventfilter.Filter{filter, prefixFilter, suffixFilter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Any filter no 1 match at end of array",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch, filter},
event: event,
name: "Any filter no 1 match at end of array",
arg: []eventfilter.Filter{prefixFilterNoMatch, suffixFilterNoMatch, filter},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Any filter no 1 match at start of array",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, suffixFilterNoMatch},
event: event,
name: "Any filter no 1 match at start of array",
arg: []eventfilter.Filter{filter, prefixFilterNoMatch, suffixFilterNoMatch},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Any filter 2 events match 2 different filters",
arg: []eventfilter.Filter{prefixFilter, prefixFilterNoMatch},
events: []cloudevents.Event{event, otherEvent},
},
FilterBenchmark{
name: "Any filter 2 events match 2 different filters, one filter in front which matches neither",
arg: []eventfilter.Filter{suffixFilterNoMatch, prefixFilter, prefixFilterNoMatch},
events: []cloudevents.Event{event, otherEvent},
},
)
}
11 changes: 6 additions & 5 deletions pkg/eventfilter/benchmarks/attributes_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"

"knative.dev/eventing/pkg/eventfilter"
Expand All @@ -33,9 +34,9 @@ func BenchmarkAttributesFilter(b *testing.B) {
return attributes.NewAttributesFilter(i.(map[string]string))
},
FilterBenchmark{
name: "Pass with exact match of id",
arg: map[string]string{"id": event.ID()},
event: event,
name: "Pass with exact match of id",
arg: map[string]string{"id": event.ID()},
events: []cloudevents.Event{event},
},
FilterBenchmark{
// We don't test time because the exact match on the string apparently doesn't work well,
Expand All @@ -49,15 +50,15 @@ func BenchmarkAttributesFilter(b *testing.B) {
"datacontenttype": event.DataContentType(),
"subject": event.Subject(),
},
event: event,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "No pass with exact match of id and source",
arg: map[string]string{
"id": "qwertyuiopasdfghjklzxcvbnm",
"source": "qwertyuiopasdfghjklzxcvbnm",
},
event: event,
events: []cloudevents.Event{event},
},
)
}
11 changes: 6 additions & 5 deletions pkg/eventfilter/benchmarks/common_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import (
)

type FilterBenchmark struct {
name string
arg interface{}
event cloudevents.Event
name string
arg interface{}
events []cloudevents.Event
}

// Avoid DCE
Expand All @@ -40,17 +40,18 @@ var Result eventfilter.FilterResult
// 2. "Run: ..." benchmark measures the time/mem to execute the filter, given a pre-built filter instance and the provided event
func RunFilterBenchmarks(b *testing.B, filterCtor func(interface{}) eventfilter.Filter, filterBenchmarks ...FilterBenchmark) {
for _, fb := range filterBenchmarks {
b.Run("Creation: "+fb.name, func(b *testing.B) {
b.Run("Creation and teardown: "+fb.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
Filter = filterCtor(fb.arg)
Filter.Cleanup()
}
})
// Filter to use for the run
f := filterCtor(fb.arg)
n := len(fb.events)
b.Run("Run: "+fb.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
Result = f.Filter(context.TODO(), fb.event)
Result = f.Filter(context.TODO(), fb.events[i%n])
}
})
f.Cleanup()
Expand Down
11 changes: 6 additions & 5 deletions pkg/eventfilter/benchmarks/exact_filter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"
"knative.dev/eventing/pkg/eventfilter"
"knative.dev/eventing/pkg/eventfilter/subscriptionsapi"
Expand All @@ -37,9 +38,9 @@ func BenchmarkExactFilter(b *testing.B) {
return filter
},
FilterBenchmark{
name: "Pass with exact match of id",
arg: map[string]string{"id": event.ID()},
event: event,
name: "Pass with exact match of id",
arg: map[string]string{"id": event.ID()},
events: []cloudevents.Event{event},
},
FilterBenchmark{
// We don't test time because the exact match on the string apparently doesn't work well,
Expand All @@ -53,15 +54,15 @@ func BenchmarkExactFilter(b *testing.B) {
"datacontenttype": event.DataContentType(),
"subject": event.Subject(),
},
event: event,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "No pass with exact match of id and source",
arg: map[string]string{
"id": "qwertyuiopasdfghjklzxcvbnm",
"source": "qwertyuiopasdfghjklzxcvbnm",
},
event: event,
events: []cloudevents.Event{event},
},
)
}
19 changes: 10 additions & 9 deletions pkg/eventfilter/benchmarks/not_filter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"
"knative.dev/eventing/pkg/eventfilter"
"knative.dev/eventing/pkg/eventfilter/subscriptionsapi"
Expand All @@ -37,19 +38,19 @@ func BenchmarkNotFilter(b *testing.B) {
return subscriptionsapi.NewNotFilter(i.(eventfilter.Filter))
},
FilterBenchmark{
name: "Not filter with exact filter test",
arg: filter,
event: event,
name: "Not filter with exact filter test",
arg: filter,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Not filter with prefix filter test",
arg: prefixFilter,
event: event,
name: "Not filter with prefix filter test",
arg: prefixFilter,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Not filter with suffix filter test",
arg: suffixFilter,
event: event,
name: "Not filter with suffix filter test",
arg: suffixFilter,
events: []cloudevents.Event{event},
},
)
}
13 changes: 7 additions & 6 deletions pkg/eventfilter/benchmarks/prefix_filter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package benchmarks
import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
cetest "github.com/cloudevents/sdk-go/v2/test"
"knative.dev/eventing/pkg/eventfilter"
"knative.dev/eventing/pkg/eventfilter/subscriptionsapi"
Expand All @@ -37,9 +38,9 @@ func BenchmarkPrefixFilter(b *testing.B) {
return filter
},
FilterBenchmark{
name: "Pass with prefix match of id",
arg: map[string]string{"id": event.ID()[0:5]},
event: event,
name: "Pass with prefix match of id",
arg: map[string]string{"id": event.ID()[0:5]},
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Pass with prefix match of all context attributes",
Expand All @@ -51,7 +52,7 @@ func BenchmarkPrefixFilter(b *testing.B) {
"datacontenttype": event.DataContentType()[0:5],
"subject": event.Subject()[0:5],
},
event: event,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "Pass with prefix match of all context attributes",
Expand All @@ -63,15 +64,15 @@ func BenchmarkPrefixFilter(b *testing.B) {
"datacontenttype": event.DataContentType()[0:3],
"subject": event.Subject()[0:3],
},
event: event,
events: []cloudevents.Event{event},
},
FilterBenchmark{
name: "No pass with prefix match of id and source",
arg: map[string]string{
"id": "qwertyuiopasdfghjklzxcvbnm",
"source": "qwertyuiopasdfghjklzxcvbnm",
},
event: event,
events: []cloudevents.Event{event},
},
)
}
Loading

0 comments on commit 3b1465a

Please sign in to comment.