From c73e3ca9aabded6dd1aa5765e961a26436b082a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 1 Sep 2023 11:55:21 +0100 Subject: [PATCH 1/4] test: benchmark feature toggle evaluation --- benchmark_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 benchmark_test.go diff --git a/benchmark_test.go b/benchmark_test.go new file mode 100644 index 0000000..bea7298 --- /dev/null +++ b/benchmark_test.go @@ -0,0 +1,50 @@ +package unleash_test + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/Unleash/unleash-client-go/v3" +) + +type NoOpListener struct{} + +func (l *NoOpListener) OnReady() {} +func (l *NoOpListener) OnError(err error) {} +func (l *NoOpListener) OnWarning(warning error) {} +func (l *NoOpListener) OnCount(name string, enabled bool) {} +func (l *NoOpListener) OnSent(payload unleash.MetricsData) {} +func (l *NoOpListener) OnRegistered(payload unleash.ClientData) {} + +func BenchmarkFeatureToggleEvaluation(b *testing.B) { + unleash.Initialize( + unleash.WithListener(&NoOpListener{}), + unleash.WithAppName("go-benchmark"), + unleash.WithUrl("https://app.unleash-hosted.com/demo/api/"), + unleash.WithCustomHeaders(http.Header{"Authorization": {"Go-Benchmark:development.be6b5d318c8e77469efb58590022bb6416100261accf95a15046c04d"}}), + ) + + b.ResetTimer() + startTime := time.Now() + + for i := 0; i < b.N; i++ { + _ = unleash.IsEnabled("go-benchmark") + } + + endTime := time.Now() + b.StopTimer() + + // Calculate ns/op (nanoseconds per operation) + nsPerOp := float64(endTime.Sub(startTime).Nanoseconds()) / float64(b.N) + + // Calculate operations per day + opsPerSec := 1e9 / nsPerOp + opsPerDay := opsPerSec * 60 * 60 * 24 + + if b.N > 1000000 { // Only print if the number of iterations is large enough for a stable result + opsPerDayTrillions := opsPerDay / 1e9 // Convert to billions + fmt.Printf("Final Estimated Operations Per Day: %.3f billion (%e)\n", opsPerDayTrillions, opsPerDay) + } +} From 6bdc57091ad034138a799d347492dea35febc46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 1 Sep 2023 14:01:32 +0100 Subject: [PATCH 2/4] fix: typo in unit - billions, not trillions --- benchmark_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark_test.go b/benchmark_test.go index bea7298..88e6c74 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -44,7 +44,7 @@ func BenchmarkFeatureToggleEvaluation(b *testing.B) { opsPerDay := opsPerSec * 60 * 60 * 24 if b.N > 1000000 { // Only print if the number of iterations is large enough for a stable result - opsPerDayTrillions := opsPerDay / 1e9 // Convert to billions - fmt.Printf("Final Estimated Operations Per Day: %.3f billion (%e)\n", opsPerDayTrillions, opsPerDay) + opsPerDayBillions := opsPerDay / 1e9 // Convert to billions + fmt.Printf("Final Estimated Operations Per Day: %.3f billion (%e)\n", opsPerDayBillions, opsPerDay) } } From b9dc62449ffb3413ba9468646a112064e58c2a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 1 Sep 2023 14:29:54 +0100 Subject: [PATCH 3/4] docs: add README mention to the new benchmark --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f77d9f3..1e4ba71 100644 --- a/README.md +++ b/README.md @@ -203,11 +203,12 @@ This client uses go routines to report several events and doesn't drain the chan ### Feature Resolver -`FeatureResolver` is a `FeatureOption` used in `IsEnabled` via the `WithResolver`. +`FeatureResolver` is a `FeatureOption` used in `IsEnabled` via the `WithResolver`. The `FeatureResolver` can be used to provide a feature instance in a different way than the client would normally retrieve it. This alternative resolver can be useful if you already have the feature instance and don't want to incur the cost to retrieve it from the repository. An example of its usage is below: + ```go ctx := context.Context{ UserId: "123", @@ -238,7 +239,7 @@ resolver := func(featureName string) *api.Feature { } } -// This would return true because the matched strategy is default and the feature is Enabled +// This would return true because the matched strategy is default and the feature is Enabled unleash.IsEnabled("someToggle", unleash.WithContext(ctx), unleash.WithResolver(resolver)) ``` @@ -286,3 +287,27 @@ Run code-style checks:(currently failing) Run race-tests: make test-race + +## Benchmarking + +You can benchmark feature toggle evaluation by running: + + go test -run=^$ -bench=BenchmarkFeatureToggleEvaluation -benchtime=10s + +Here's an example of how the output could look like: + +``` +goos: darwin +goarch: arm64 +pkg: github.com/Unleash/unleash-client-go/v3 +BenchmarkFeatureToggleEvaluation-8 Final Estimated Operations Per Day: 101.131 billion (1.011315e+11) +13635154 854.3 ns/op +PASS +ok github.com/Unleash/unleash-client-go/v3 13.388s +``` + +In this example the benchmark was run on a MacBook Pro (M1 Pro, 2021) with 16GB RAM. + +We can see a result of **854.3 ns/op**, which means around **101.131 billion** feature toggle evaluations per day. + +**Note**: The benchmark is run with a single CPU core, no parallelism. From 908e4125ed0b0e75d04c0ce0fbd7dadc5180d714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 1 Sep 2023 15:33:08 +0100 Subject: [PATCH 4/4] docs: fence code block --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e4ba71..fbf3757 100644 --- a/README.md +++ b/README.md @@ -292,7 +292,9 @@ Run race-tests: You can benchmark feature toggle evaluation by running: - go test -run=^$ -bench=BenchmarkFeatureToggleEvaluation -benchtime=10s +``` +go test -run=^$ -bench=BenchmarkFeatureToggleEvaluation -benchtime=10s +``` Here's an example of how the output could look like: