From c1678424b67bda775e1728ceb20a440ca1292196 Mon Sep 17 00:00:00 2001 From: Ian Luo <ian.luo@gmail.com> Date: Wed, 19 Aug 2020 13:28:27 +0800 Subject: [PATCH] avoid of copying and comparing invokers as much as possible --- cluster/router/chain/chain.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/cluster/router/chain/chain.go b/cluster/router/chain/chain.go index a7f139b23..b15b845cf 100644 --- a/cluster/router/chain/chain.go +++ b/cluster/router/chain/chain.go @@ -167,21 +167,35 @@ func (c *RouterChain) loadCache() *InvokerCache { return v.(*InvokerCache) } +// copyInvokerIfNecessary compares chain's invokers copy and cache's invokers copy, to avoid copy as much as possible +func (c *RouterChain) copyInvokerIfNecessary(cache *InvokerCache) []protocol.Invoker { + var invokers []protocol.Invoker + if cache != nil { + invokers = cache.invokers + } + + c.mutex.RLock() + defer c.mutex.RUnlock() + if isInvokersChanged(invokers, c.invokers) { + invokers = c.copyInvokers() + } + return invokers +} + // buildCache builds address cache with the new invokers for all poolable routers. func (c *RouterChain) buildCache() { - invokers := c.copyInvokers() - if invokers == nil || len(c.invokers) == 0 { + origin := c.loadCache() + invokers := c.copyInvokerIfNecessary(origin) + if invokers == nil || len(invokers) == 0 { return } - cache := BuildCache(invokers) - origin := c.loadCache() - var ( mutex sync.Mutex wg sync.WaitGroup ) + cache := BuildCache(invokers) for _, r := range c.copyRouters() { if p, ok := r.(router.Poolable); ok { wg.Add(1) @@ -246,7 +260,7 @@ func NewRouterChain(url *common.URL) (*RouterChain, error) { // rule doesn't change), and the address list doesn't change, then the existing data will be re-used. func poolRouter(p router.Poolable, origin *InvokerCache, invokers []protocol.Invoker) (router.AddrPool, router.AddrMetadata) { name := p.Name() - if isCacheMiss(origin, name) || p.ShouldPool() || isInvokersChanged(origin.invokers, invokers) { + if isCacheMiss(origin, name) || p.ShouldPool() || &(origin.invokers) != &invokers { logger.Debugf("build address cache for router %q", name) return p.Pool(invokers) } -- GitLab