This is an automated email from the ASF dual-hosted git repository.

Alanxtl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 1ce8314a0 Feat: add benchmarks for common.URL (#3399)
1ce8314a0 is described below

commit 1ce8314a06eb9a51c3d9befc5878e23dd15b62e7
Author: wm_03 <[email protected]>
AuthorDate: Fri Jun 12 11:28:45 2026 +0800

    Feat: add benchmarks for common.URL (#3399)
    
    * test: add benchmarks for common.URL.
    
    * test: keep full identity params across URL benchmark tiers
    
    * test: add URL filter benchmarks with nested sub-URLs
---
 common/url_benchmark_test.go | 320 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)

diff --git a/common/url_benchmark_test.go b/common/url_benchmark_test.go
new file mode 100644
index 000000000..1e904957a
--- /dev/null
+++ b/common/url_benchmark_test.go
@@ -0,0 +1,320 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package common
+
+import (
+       "fmt"
+       "net/url"
+       "testing"
+)
+
+import (
+       gxset "github.com/dubbogo/gost/container/set"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+const (
+       benchmarkURLProtocol  = "dubbo"
+       benchmarkURLIP        = "127.0.0.1"
+       benchmarkURLPort      = "20000"
+       benchmarkURLInterface = "com.test.BenchmarkService"
+       benchmarkURLGroup     = "benchmark"
+       benchmarkURLVersion   = "1.0.0"
+       benchmarkURLTimestamp = "1234567890"
+       benchmarkURLMeshID    = "benchmark-mesh"
+)
+
+var (
+       benchmarkURLParamSizes = []int{1, 32, 256, 1024}
+
+       benchmarkURLStringSink string
+       benchmarkURLSink       *URL
+       benchmarkURLParamsSink url.Values
+       benchmarkURLMapSink    map[string]string
+       benchmarkURLBoolSink   bool
+)
+
+func BenchmarkURLString(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLStringSink = u.String()
+       })
+}
+
+func BenchmarkURLKey(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLStringSink = u.Key()
+       })
+}
+
+func BenchmarkURLGetCacheInvokerMapKey(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLStringSink = u.GetCacheInvokerMapKey()
+       })
+}
+
+func BenchmarkURLServiceKey(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLStringSink = u.ServiceKey()
+       })
+}
+
+func BenchmarkURLCopyParams(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLParamsSink = u.CopyParams()
+       })
+}
+
+func BenchmarkURLGetParams(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLParamsSink = u.GetParams()
+       })
+}
+
+func BenchmarkURLClone(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLSink = u.Clone()
+       })
+
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_with_suburl", paramCount), func(b 
*testing.B) {
+                       u := makeBenchmarkURLWithSubURL(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = u.Clone()
+                       }
+               })
+       }
+}
+
+func BenchmarkURLCloneWithFilter(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLSink = u.CloneWithFilter(nil, nil)
+       })
+
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_exclude_20_percent", paramCount), 
func(b *testing.B) {
+                       u := makeBenchmarkURL(paramCount)
+                       excludeParams := makeBenchmarkExcludeSet(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = 
u.CloneWithFilter(excludeParams, nil)
+                       }
+               })
+       }
+
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_exclude_20_percent_with_suburl", 
paramCount), func(b *testing.B) {
+                       u := makeBenchmarkURLWithSubURL(paramCount)
+                       excludeParams := makeBenchmarkExcludeSet(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = 
u.CloneWithFilter(excludeParams, nil)
+                       }
+               })
+       }
+
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_reserve_20_percent", paramCount), 
func(b *testing.B) {
+                       u := makeBenchmarkURL(paramCount)
+                       reserveParams := makeBenchmarkReserveKeys(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = u.CloneWithFilter(nil, 
reserveParams)
+                       }
+               })
+       }
+
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_reserve_20_percent_with_suburl", 
paramCount), func(b *testing.B) {
+                       u := makeBenchmarkURLWithSubURL(paramCount)
+                       reserveParams := makeBenchmarkReserveKeys(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = u.CloneWithFilter(nil, 
reserveParams)
+                       }
+               })
+       }
+}
+
+func BenchmarkURLMergeURL(b *testing.B) {
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d_with_method_params", paramCount), 
func(b *testing.B) {
+                       left, right := 
makeBenchmarkMergeHalfOverlapPair(paramCount)
+                       addBenchmarkMethodParams(right)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLSink = left.MergeURL(right)
+                       }
+               })
+       }
+}
+
+func BenchmarkURLToMap(b *testing.B) {
+       runBenchmarkURLByParamSize(b, func(u *URL) {
+               benchmarkURLMapSink = u.ToMap()
+       })
+}
+
+func BenchmarkURLIsEquals(b *testing.B) {
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d", paramCount), func(b *testing.B) {
+                       left := makeBenchmarkURL(paramCount)
+                       right := makeBenchmarkURL(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               benchmarkURLBoolSink = IsEquals(left, right)
+                       }
+               })
+       }
+}
+
+func runBenchmarkURLByParamSize(b *testing.B, run func(*URL)) {
+       b.Helper()
+       for _, paramCount := range benchmarkURLParamSizes {
+               paramCount := paramCount
+               b.Run(fmt.Sprintf("params_%d", paramCount), func(b *testing.B) {
+                       u := makeBenchmarkURL(paramCount)
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               run(u)
+                       }
+               })
+       }
+}
+
+func makeBenchmarkURL(paramCount int) *URL {
+       return makeBenchmarkURLWithParamStart(paramCount, 0)
+}
+
+func makeBenchmarkURLWithSubURL(paramCount int) *URL {
+       u := makeBenchmarkURL(paramCount)
+       u.SubURL = makeBenchmarkURL(paramCount)
+       return u
+}
+
+func makeBenchmarkURLWithParamStart(paramCount, genericStart int) *URL {
+       u := NewURLWithOptions(
+               WithProtocol(benchmarkURLProtocol),
+               WithIp(benchmarkURLIP),
+               WithPort(benchmarkURLPort),
+               WithPath(benchmarkURLInterface),
+               WithMethods(makeBenchmarkMethods()),
+               WithParams(makeBenchmarkParams(paramCount, genericStart)),
+       )
+       u.primitiveTS = u.GetParam(constant.TimestampKey, "")
+       return u
+}
+
+func makeBenchmarkMergeHalfOverlapPair(paramCount int) (*URL, *URL) {
+       return makeBenchmarkURL(paramCount), 
makeBenchmarkURLWithParamStart(paramCount, paramCount/2)
+}
+
+func makeBenchmarkParams(paramCount, genericStart int) url.Values {
+       params := make(url.Values, len(benchmarkURLIdentityParams)+paramCount)
+       for _, param := range benchmarkURLIdentityParams {
+               params.Set(param.key, param.value)
+       }
+       for i := 0; i < paramCount; i++ {
+               genericIndex := genericStart + i
+               params.Set(fmt.Sprintf("key%d", genericIndex), 
fmt.Sprintf("value%d", genericIndex))
+       }
+       return params
+}
+
+func makeBenchmarkParamKeys(paramCount int) []string {
+       keys := make([]string, 0, len(benchmarkURLIdentityParams)+paramCount)
+       for _, param := range benchmarkURLIdentityParams {
+               keys = append(keys, param.key)
+       }
+       for i := 0; i < paramCount; i++ {
+               keys = append(keys, fmt.Sprintf("key%d", i))
+       }
+       return keys
+}
+
+func makeBenchmarkExcludeSet(paramCount int) *gxset.HashSet {
+       keys := makeBenchmarkFilterKeys(paramCount)
+       values := make([]any, 0, len(keys))
+       for _, key := range keys {
+               values = append(values, key)
+       }
+       return gxset.NewSet(values...)
+}
+
+func makeBenchmarkReserveKeys(paramCount int) []string {
+       return makeBenchmarkFilterKeys(paramCount)
+}
+
+func makeBenchmarkFilterKeys(paramCount int) []string {
+       keys := makeBenchmarkParamKeys(paramCount)
+       filterCount := len(keys) / 5
+       if filterCount < 1 {
+               filterCount = 1
+       }
+       if filterCount > len(keys) {
+               filterCount = len(keys)
+       }
+       return keys[:filterCount]
+}
+
+func makeBenchmarkMethods() []string {
+       return []string{"method0", "method1", "method2"}
+}
+
+func addBenchmarkMethodParams(u *URL) {
+       u.Methods = makeBenchmarkMethods()
+       u.SetParam(constant.LoadbalanceKey, "random")
+       u.SetParam(constant.ClusterKey, "failover")
+       u.SetParam(constant.RetriesKey, "2")
+       u.SetParam(constant.TimeoutKey, "3000")
+       for _, method := range u.Methods {
+               u.SetParam("methods."+method+"."+constant.LoadbalanceKey, 
"roundrobin")
+               u.SetParam("methods."+method+"."+constant.ClusterKey, 
"failfast")
+               u.SetParam("methods."+method+"."+constant.RetriesKey, "1")
+               u.SetParam("methods."+method+"."+constant.TimeoutKey, "1000")
+       }
+}
+
+var benchmarkURLIdentityParams = []struct {
+       key   string
+       value string
+}{
+       {constant.InterfaceKey, benchmarkURLInterface},
+       {constant.GroupKey, benchmarkURLGroup},
+       {constant.VersionKey, benchmarkURLVersion},
+       {constant.TimestampKey, benchmarkURLTimestamp},
+       {constant.MeshClusterIDKey, benchmarkURLMeshID},
+}

Reply via email to