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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 9c0cd206a Feat(cluster): reduce endpoint cloning (#961)
9c0cd206a is described below

commit 9c0cd206aa7774208978276e4daff52e99a5500d
Author: wm_03 <[email protected]>
AuthorDate: Mon Jul 6 20:16:52 2026 +0800

    Feat(cluster): reduce endpoint cloning (#961)
    
    * test(cluster): adds endpoint membership churn benchmark.
    
    * feat(cluster): Avoid recloning store-owned endpoints
    
    * feat(cluster): drop redundant nil guards
    
    * feat(cluster): use slices.Delete for endpoint removal
---
 pkg/server/cluster_manager.go            | 33 +++++++++++++++++++++-----------
 pkg/server/cluster_manager_bench_test.go | 33 ++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/pkg/server/cluster_manager.go b/pkg/server/cluster_manager.go
index c708e60b4..09a4dd7a5 100644
--- a/pkg/server/cluster_manager.go
+++ b/pkg/server/cluster_manager.go
@@ -20,6 +20,7 @@ package server
 import (
        "fmt"
        "reflect"
+       "slices"
        "sync"
        "sync/atomic"
 )
@@ -356,23 +357,33 @@ func (s *ClusterStore) AddCluster(c *model.ClusterConfig) 
{
        stopClusters([]*cluster.Cluster{s.replaceClusterRuntime(c.Name, c)})
 }
 
-// prepareClusterConfig rebuilds endpoint defaults and hash from current 
endpoints.
+// prepareClusterConfig clones operator-supplied endpoints, then rebuilds
+// endpoint defaults and hash from current endpoints.
 func (s *ClusterStore) prepareClusterConfig(c *model.ClusterConfig) {
+       c.Endpoints = model.CloneEndpoints(c.Endpoints)
+       s.prepareOwnedClusterConfig(c)
+}
+
+// prepareOwnedClusterConfig rebuilds endpoint defaults and hash for endpoints
+// already owned by ClusterStore. Callers must not pass operator-owned endpoint
+// pointers here; use prepareClusterConfig at external input boundaries.
+func (s *ClusterStore) prepareOwnedClusterConfig(c *model.ClusterConfig) {
        s.assembleClusterEndpoints(c)
        c.CreateConsistentHash()
 }
 
-// assembleClusterEndpoints assembles the cluster endpoints by formatting the
-// ID, name and domains for each endpoint. If endpoint.LLMMeta is not nil, the
-// assimilation of name and domain is based on the LLM provider denoted in the
-// endpoint LLMMeta. The store first deep-clones c.Endpoints, so ID/name
-// defaulting never mutates operator-supplied *model.Endpoint values.
+// assembleClusterEndpoints assembles the cluster endpoints by assigning stable
+// unique IDs and default names for each endpoint. If endpoint.LLMMeta is not 
nil,
+// the default endpoint name is based on the LLM provider denoted in the 
endpoint
+// LLMMeta. Callers choose the ownership boundary before invoking this helper:
+// external input paths clone endpoints in prepareClusterConfig, while 
store-owned
+// mutation paths call prepareOwnedClusterConfig to avoid a second full 
endpoint
+// clone before snapshot publication.
 func (s *ClusterStore) assembleClusterEndpoints(c *model.ClusterConfig) {
        if c == nil {
                return
        }
 
-       c.Endpoints = model.CloneEndpoints(c.Endpoints)
        endpointIDs := make(map[string]struct{}, len(c.Endpoints))
        for i, endpoint := range c.Endpoints {
                if endpoint == nil {
@@ -642,7 +653,7 @@ func (s *ClusterStore) SetEndpoint(clusterName string, 
endpoint *model.Endpoint)
                s.replaceEndpointAt(clusterConfig, runtimeCluster, 
outcome.replaceIdx, endpoint)
        case setEndpointAppend:
                clusterConfig.Endpoints = append(clusterConfig.Endpoints, 
endpoint)
-               s.prepareClusterConfig(clusterConfig)
+               s.prepareOwnedClusterConfig(clusterConfig)
                runtimeCluster.RefreshEndpoints()
                runtimeCluster.AddEndpoint(endpoint)
        }
@@ -677,7 +688,7 @@ func (s *ClusterStore) replaceEndpointAt(
                logSetEndpointOverwrite(clusterConfig.Name, endpoint.ID, old, 
endpoint)
        }
        clusterConfig.Endpoints[idx] = endpoint
-       s.prepareClusterConfig(clusterConfig)
+       s.prepareOwnedClusterConfig(clusterConfig)
        runtimeCluster.RefreshEndpoints()
        if addressChanged {
                runtimeCluster.AddEndpoint(endpoint)
@@ -941,8 +952,8 @@ func (s *ClusterStore) DeleteEndpoint(clusterName string, 
endpointID string) {
        for i, e := range clusterConfig.Endpoints {
                if e.ID == endpointID {
                        runtimeCluster.RemoveEndpoint(e)
-                       clusterConfig.Endpoints = 
append(clusterConfig.Endpoints[:i], clusterConfig.Endpoints[i+1:]...)
-                       s.prepareClusterConfig(clusterConfig)
+                       clusterConfig.Endpoints = 
slices.Delete(clusterConfig.Endpoints, i, i+1)
+                       s.prepareOwnedClusterConfig(clusterConfig)
                        runtimeCluster.RefreshEndpoints()
                        return
                }
diff --git a/pkg/server/cluster_manager_bench_test.go 
b/pkg/server/cluster_manager_bench_test.go
index d7b7a2563..63faf3db0 100644
--- a/pkg/server/cluster_manager_bench_test.go
+++ b/pkg/server/cluster_manager_bench_test.go
@@ -165,6 +165,39 @@ func benchmarkHealthySnapshotAccessor(
        }
 }
 
+func BenchmarkClusterSetEndpointMembershipChurn(b *testing.B) {
+       endpointCount := 1000
+       clusterName := "endpoint-churn"
+
+       clusterConfig := benchmarkClusterConfig(clusterName, 
model.LoadBalancerRoundRobin, endpointCount, 0)
+       for _, endpoint := range clusterConfig.Endpoints {
+               endpoint.Metadata = map[string]string{
+                       "first":  "0",
+                       "second": "0",
+                       "third":  "0",
+               }
+       }
+
+       cm := testClusterManager(clusterConfig)
+       endpoints := cm.store.Config[0].Endpoints
+
+       b.ReportAllocs()
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               endpoint := endpoints[i%len(endpoints)]
+
+               cm.SetEndpoint(clusterName, &model.Endpoint{
+                       ID:      endpoint.ID,
+                       Address: endpoint.Address,
+                       Metadata: map[string]string{
+                               "first":  fmt.Sprintf("%d", i),
+                               "second": fmt.Sprintf("%d", i),
+                               "third":  fmt.Sprintf("%d", i),
+                       },
+               })
+       }
+}
+
 func BenchmarkClusterCompareAndSetStoreMixed(b *testing.B) {
        cm, names := benchmarkClusterManager(128, 4, 
model.LoadBalancerRoundRobin)
        readIndex := 0

Reply via email to