*: update google/btree to improve performance (#547)

* *: update google/btree to improve performance

Signed-off-by: Weizhen Wang <wangweizhen@pingcap.com>

* update ci

Signed-off-by: Weizhen Wang <wangweizhen@pingcap.com>
This commit is contained in:
Weizhen Wang 2022-07-18 16:02:14 +08:00 committed by GitHub
parent 57c12f7c64
commit 86d51ba7eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 358 additions and 1161 deletions

View File

@ -1,6 +1,6 @@
module gcworker
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module rawkv
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module 1pc_txn
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module async_commit
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module delete_range
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module txnkv
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module pessimistic_txn
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

View File

@ -1,6 +1,6 @@
module unsafedestoryrange
go 1.16
go 1.18
require github.com/tikv/client-go/v2 v2.0.0

35
go.mod
View File

@ -1,18 +1,15 @@
module github.com/tikv/client-go/v2
go 1.16
go 1.18
require (
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf // indirect
github.com/google/btree v1.0.0
github.com/google/btree v1.1.2
github.com/google/uuid v1.1.2
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.18.1 // indirect
github.com/opentracing/opentracing-go v1.2.0
github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00
github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989
@ -21,7 +18,6 @@ require (
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/client_model v0.2.0
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/stathat/consistent v1.0.0
github.com/stretchr/testify v1.7.0
github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710
@ -33,5 +29,32 @@ require (
go.uber.org/zap v1.20.0
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/grpc v1.43.0
)
require (
github.com/benbjohnson/clock v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.18.1 // indirect
github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
stathat.com/c/consistent v1.0.0 // indirect
)

4
go.sum
View File

@ -84,8 +84,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf h1:gFVkHXmVAhEbxZVDln5V9GKrLaluNoFHDbrZwAWZgws=
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=

View File

@ -1,15 +1,13 @@
module integration_tests
go 1.16
go 1.18
require (
github.com/klauspost/compress v1.15.4 // indirect
github.com/ninedraft/israce v0.0.3
github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c
github.com/pingcap/failpoint v0.0.0-20220423142525-ae43b7f4e5c3
github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a
github.com/pingcap/tidb v1.1.0-beta.0.20220706093502-562b03368993
github.com/pingcap/tidb/parser v0.0.0-20220706093502-562b03368993 // indirect
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.2-0.20220504104629-106ec21d14df
github.com/tidwall/gjson v1.14.1
@ -18,6 +16,75 @@ require (
go.uber.org/goleak v1.1.12
)
require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/coocood/bbloom v0.0.0-20190830030839-58deb6228d64 // indirect
github.com/coocood/freecache v1.2.1 // indirect
github.com/coocood/rtutil v0.0.0-20190304133409-c84515f646f2 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
github.com/danjacques/gofslock v0.0.0-20191023191349-0a45f885bc37 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/klauspost/compress v1.15.4 // indirect
github.com/klauspost/cpuid v1.3.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/ncw/directio v1.0.5 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/opentracing/basictracer-go v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pingcap/badger v1.5.1-0.20220314162537-ab58fbf40580 // indirect
github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 // indirect
github.com/pingcap/log v1.1.0 // indirect
github.com/pingcap/tidb/parser v0.0.0-20220706093502-562b03368993 // indirect
github.com/pingcap/tipb v0.0.0-20220706024432-7be3cc83a7d5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/shirou/gopsutil/v3 v3.22.4 // indirect
github.com/stathat/consistent v1.0.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twmb/murmur3 v1.1.3 // indirect
github.com/uber/jaeger-client-go v2.22.1+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.2 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect
go.etcd.io/etcd/client/v3 v3.5.2 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/exp v0.0.0-20220428152302-39d4317da171 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
golang.org/x/tools v0.1.11 // indirect
google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8 // indirect
google.golang.org/grpc v1.44.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
replace github.com/tikv/client-go/v2 => ../
replace github.com/pingcap/tidb => github.com/glorv/tidb v1.1.0-beta.0.20220706085636-88fb3fa642bb

File diff suppressed because it is too large Load Diff

View File

@ -371,7 +371,7 @@ type RegionCache struct {
sync.RWMutex // mutex protect cached region
regions map[RegionVerID]*Region // cached regions are organized as regionVerID to region ref mapping
latestVersions map[uint64]RegionVerID // cache the map from regionID to its latest RegionVerID
sorted *btree.BTree // cache regions are organized as sorted key to region ref mapping
sorted *SortedRegions // cache regions are organized as sorted key to region ref mapping
}
storeMu struct {
sync.RWMutex
@ -410,7 +410,7 @@ func NewRegionCache(pdClient pd.Client) *RegionCache {
c.mu.regions = make(map[RegionVerID]*Region)
c.mu.latestVersions = make(map[uint64]RegionVerID)
c.mu.sorted = btree.New(btreeDegree)
c.mu.sorted = NewSortedRegions(btreeDegree)
c.storeMu.stores = make(map[uint64]*Store)
c.tiflashMPPStoreMu.needReload = true
c.tiflashMPPStoreMu.stores = make([]*Store, 0)
@ -427,7 +427,7 @@ func (c *RegionCache) clear() {
c.mu.Lock()
c.mu.regions = make(map[RegionVerID]*Region)
c.mu.latestVersions = make(map[uint64]RegionVerID)
c.mu.sorted = btree.New(btreeDegree)
c.mu.sorted.Clear()
c.mu.Unlock()
c.storeMu.Lock()
c.storeMu.stores = make(map[uint64]*Store)
@ -1284,10 +1284,9 @@ func (c *RegionCache) removeVersionFromCache(oldVer RegionVerID, regionID uint64
// insertRegionToCache tries to insert the Region to cache.
// It should be protected by c.mu.Lock().
func (c *RegionCache) insertRegionToCache(cachedRegion *Region) {
old := c.mu.sorted.ReplaceOrInsert(newBtreeItem(cachedRegion))
if old != nil {
oldRegion := c.mu.sorted.ReplaceOrInsert(cachedRegion)
if oldRegion != nil {
store := cachedRegion.getStore()
oldRegion := old.(*btreeItem).cachedRegion
oldRegionStore := oldRegion.getStore()
// TODO(youjiali1995): remove this because the new retry logic can handle this issue.
//
@ -1328,18 +1327,7 @@ func (c *RegionCache) searchCachedRegion(key []byte, isEndKey bool) *Region {
ts := time.Now().Unix()
var r *Region
c.mu.RLock()
c.mu.sorted.DescendLessOrEqual(newBtreeSearchItem(key), func(item btree.Item) bool {
r = item.(*btreeItem).cachedRegion
if isEndKey && bytes.Equal(r.StartKey(), key) {
r = nil // clear result
return true // iterate next item
}
if !r.checkRegionCacheTTL(ts) {
r = nil
return true
}
return false
})
r = c.mu.sorted.DescendLessOrEqual(key, isEndKey, ts)
c.mu.RUnlock()
if r != nil && (!isEndKey && r.Contains(key) || isEndKey && r.ContainsByEnd(key)) {
return r
@ -1532,14 +1520,7 @@ func (c *RegionCache) scanRegionsFromCache(bo *retry.Backoffer, startKey, endKey
var regions []*Region
c.mu.RLock()
defer c.mu.RUnlock()
c.mu.sorted.AscendGreaterOrEqual(newBtreeSearchItem(startKey), func(item btree.Item) bool {
region := item.(*btreeItem).cachedRegion
if len(endKey) > 0 && bytes.Compare(region.StartKey(), endKey) >= 0 {
return false
}
regions = append(regions, region)
return len(regions) < limit
})
regions = c.mu.sorted.AscendGreaterOrEqual(startKey, endKey, limit)
if len(regions) == 0 {
return nil, errors.New("no regions in the cache")

View File

@ -44,7 +44,6 @@ import (
"time"
"github.com/gogo/protobuf/proto"
"github.com/google/btree"
"github.com/pingcap/kvproto/pkg/errorpb"
"github.com/pingcap/kvproto/pkg/metapb"
"github.com/stretchr/testify/suite"
@ -98,7 +97,7 @@ func (s *testRegionCacheSuite) checkCache(len int) {
ts := time.Now().Unix()
s.Equal(validRegions(s.cache.mu.regions, ts), len)
s.Equal(validRegionsSearchedByVersions(s.cache.mu.latestVersions, s.cache.mu.regions, ts), len)
s.Equal(validRegionsInBtree(s.cache.mu.sorted, ts), len)
s.Equal(s.cache.mu.sorted.ValidRegionsInBtree(ts), len)
}
func validRegionsSearchedByVersions(
@ -126,18 +125,6 @@ func validRegions(regions map[RegionVerID]*Region, ts int64) (len int) {
return
}
func validRegionsInBtree(t *btree.BTree, ts int64) (len int) {
t.Descend(func(item btree.Item) bool {
r := item.(*btreeItem).cachedRegion
if !r.checkRegionCacheTTL(ts) {
return true
}
len++
return true
})
return
}
func (s *testRegionCacheSuite) getRegion(key []byte) *Region {
_, err := s.cache.LocateKey(s.bo, key)
s.Nil(err)

View File

@ -0,0 +1,113 @@
// Copyright 2022 TiKV Authors
//
// Licensed 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.
// NOTE: The code in this file is based on code from the
// TiDB project, licensed under the Apache License v 2.0
//
// https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/locate/region_request.go
//
// Copyright 2016 PingCAP, Inc.
//
// Licensed 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.
//go:build !go1.18
// +build !go1.18
package locate
import (
"bytes"
"github.com/google/btree"
)
// SortedRegionsRegions is a sorted btree.
type SortedRegions struct {
b *btree.BTree
}
// NewSortedRegions returns a new SortedRegions.
func NewSortedRegions(btreeDegree int) *SortedRegions {
return &SortedRegions{
b: btree.New(btreeDegree),
}
}
// ReplaceOrInsert inserts a new item into the btree.
func (s *SortedRegions) ReplaceOrInsert(cachedRegion *Region) *Region {
old := s.b.ReplaceOrInsert(newBtreeItem(cachedRegion))
if old != nil {
return old.(*btreeItem).cachedRegion
}
return nil
}
// DescendLessOrEqual returns all items that are less than or equal to the key.
func (s *SortedRegions) DescendLessOrEqual(key []byte, isEndKey bool, ts int64) (r *Region) {
s.b.DescendLessOrEqual(newBtreeSearchItem(key), func(item btree.Item) bool {
r = item.(*btreeItem).cachedRegion
if isEndKey && bytes.Equal(r.StartKey(), key) {
r = nil // clear result
return true // iterate next item
}
if !r.checkRegionCacheTTL(ts) {
r = nil
return true
}
return false
})
return r
}
// AscendGreaterOrEqual returns all items that are greater than or equal to the key.
func (s *SortedRegions) AscendGreaterOrEqual(startKey, endKey []byte, limit int) (regions []*Region) {
s.b.AscendGreaterOrEqual(newBtreeSearchItem(startKey), func(item btree.Item) bool {
region := item.(*btreeItem).cachedRegion
if len(endKey) > 0 && bytes.Compare(region.StartKey(), endKey) >= 0 {
return false
}
regions = append(regions, region)
return len(regions) < limit
})
return regions
}
// Clear removes all items from the btree.
func (s *SortedRegions) Clear() {
s.b.Clear(false)
}
// ValidRegionsInBtree returns the number of valid regions in the btree.
func (s *SortedRegions) ValidRegionsInBtree(ts int64) (len int) {
s.b.Descend(func(item btree.Item) bool {
r := item.(*btreeItem).cachedRegion
if !r.checkRegionCacheTTL(ts) {
return true
}
len++
return true
})
return
}

View File

@ -0,0 +1,113 @@
// Copyright 2022 TiKV Authors
//
// Licensed 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.
// NOTE: The code in this file is based on code from the
// TiDB project, licensed under the Apache License v 2.0
//
// https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/locate/region_request.go
//
// Copyright 2016 PingCAP, Inc.
//
// Licensed 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.
//go:build go1.18
// +build go1.18
package locate
import (
"bytes"
"github.com/google/btree"
)
// SortedRegions is a sorted btree.
type SortedRegions struct {
b *btree.BTreeG[*btreeItem]
}
// NewSortedRegions returns a new SortedRegions.
func NewSortedRegions(btreeDegree int) *SortedRegions {
return &SortedRegions{
b: btree.NewG(btreeDegree, func(a, b *btreeItem) bool { return a.Less(b) }),
}
}
// ReplaceOrInsert inserts a new item into the btree.
func (s *SortedRegions) ReplaceOrInsert(cachedRegion *Region) *Region {
old, _ := s.b.ReplaceOrInsert(newBtreeItem(cachedRegion))
if old != nil {
return old.cachedRegion
}
return nil
}
// DescendLessOrEqual returns all items that are less than or equal to the key.
func (s *SortedRegions) DescendLessOrEqual(key []byte, isEndKey bool, ts int64) (r *Region) {
s.b.DescendLessOrEqual(newBtreeSearchItem(key), func(item *btreeItem) bool {
r = item.cachedRegion
if isEndKey && bytes.Equal(r.StartKey(), key) {
r = nil // clear result
return true // iterate next item
}
if !r.checkRegionCacheTTL(ts) {
r = nil
return true
}
return false
})
return r
}
// AscendGreaterOrEqual returns all items that are greater than or equal to the key.
func (s *SortedRegions) AscendGreaterOrEqual(startKey, endKey []byte, limit int) (regions []*Region) {
s.b.AscendGreaterOrEqual(newBtreeSearchItem(startKey), func(item *btreeItem) bool {
region := item.cachedRegion
if len(endKey) > 0 && bytes.Compare(region.StartKey(), endKey) >= 0 {
return false
}
regions = append(regions, region)
return len(regions) < limit
})
return regions
}
// Clear removes all items from the btree.
func (s *SortedRegions) Clear() {
s.b.Clear(false)
}
// ValidRegionsInBtree returns the number of valid regions in the btree.
func (s *SortedRegions) ValidRegionsInBtree(ts int64) (len int) {
s.b.Descend(func(item *btreeItem) bool {
r := item.cachedRegion
if !r.checkRegionCacheTTL(ts) {
return true
}
len++
return true
})
return
}