Repository: tikv/pd
Pull request #5628 (2022-10-24 06:25:18)

*: reduce call when comparing key
Signed-off-by: Ryan Leung <rleungx@gmail.com>

<!--
Thank you for working on PD! Please read PD's [CONTRIBUTING](https://github.com/tikv/pd/blob/master/CONTRIBUTING.md) document **BEFORE** filing this PR.
PR Title Format:
1. pkg [, pkg2, pkg3]: what's changed
2. *: what's changed
-->

### What problem does this PR solve?

<!--

Please create an issue first to describe the problem.
There MUST be one line starting with "Issue Number:  " and 
linking the relevant issues via the "close" or "ref".
For more info, check https://github.com/tikv/pd/blob/master/CONTRIBUTING.md#linking-issues.

-->
Issue Number: Ref #5606.

### What is changed and how does it work?
```
go test -benchmem -count 5 -run=^$ -bench ^BenchmarkLoadRegionsByVolume$ github.com/tikv/pd/server/storage

name                                       old time/op    new time/op    delta
LoadRegionsByVolume/input_size_10000-40      0.05ns ±13%    0.04ns ±25%     ~     (p=0.056 n=5+5)
LoadRegionsByVolume/input_size_100000-40     0.60ns ± 9%    0.47ns ± 6%  -21.15%  (p=0.008 n=5+5)
LoadRegionsByVolume/input_size_1000000-40     6.84s ± 3%     5.35s ± 6%  -21.84%  (p=0.008 n=5+5)

name                                       old alloc/op   new alloc/op   delta
LoadRegionsByVolume/input_size_10000-40       0.00B          0.00B          ~     (all equal)
LoadRegionsByVolume/input_size_100000-40      0.00B          0.00B          ~     (all equal)
LoadRegionsByVolume/input_size_1000000-40     934MB ± 0%     933MB ± 0%   -0.01%  (p=0.032 n=5+5)

name                                       old allocs/op  new allocs/op  delta
LoadRegionsByVolume/input_size_10000-40        0.00           0.00          ~     (all equal)
LoadRegionsByVolume/input_size_100000-40       0.00           0.00          ~     (all equal)
LoadRegionsByVolume/input_size_1000000-40     15.2M ± 0%     15.2M ± 0%     ~     (p=0.421 n=5+5)
```
```
go test -benchmem -count 5 -run=^$ -bench ^BenchmarkLoadRegionsByRandomMerge$ github.com/tikv/pd/server/storage

name                                        old time/op    new time/op    delta
LoadRegionsByRandomMerge/merge_ratio_0-40      6.47s ± 6%     5.33s ± 5%  -17.62%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_20-40     7.99s ± 3%     7.01s ± 4%  -12.32%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_40-40     9.69s ± 5%     8.64s ± 4%  -10.86%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_60-40     11.1s ± 2%      9.9s ± 5%  -10.40%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_80-40     12.4s ± 3%     11.2s ± 5%   -9.74%  (p=0.008 n=5+5)

name                                        old alloc/op   new alloc/op   delta
LoadRegionsByRandomMerge/merge_ratio_0-40      934MB ± 0%     933MB ± 0%   -0.01%  (p=0.032 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_20-40    1.01GB ± 0%    1.01GB ± 0%     ~     (p=0.056 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_40-40    1.10GB ± 0%    1.10GB ± 0%   +0.06%  (p=0.032 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_60-40    1.17GB ± 0%    1.17GB ± 0%   +0.08%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_80-40    1.25GB ± 0%    1.25GB ± 0%   +0.09%  (p=0.016 n=5+5)

name                                        old allocs/op  new allocs/op  delta
LoadRegionsByRandomMerge/merge_ratio_0-40      15.2M ± 0%     15.2M ± 0%     ~     (p=0.151 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_20-40     18.0M ± 0%     18.0M ± 0%     ~     (p=0.421 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_40-40     20.7M ± 0%     20.7M ± 0%     ~     (p=0.151 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_60-40     23.3M ± 0%     23.3M ± 0%   +0.00%  (p=0.008 n=5+5)
LoadRegionsByRandomMerge/merge_ratio_80-40     25.8M ± 0%     25.8M ± 0%     ~     (p=0.151 n=5+5)
```

<!--

You could use the "commit message" code block to add more description to the final commit message.
For more info, check https://github.com/tikv/pd/blob/master/CONTRIBUTING.md#format-of-the-commit-message.

-->

```commit-message
```

### Check List

<!-- Remove the items that are not applicable. -->

Tests

<!-- At least one of these tests must be included. -->

- Unit test

### Release note

<!-- A bugfix or a new feature needs a release note. If there is no need release note, just uncomment the below line. -->

```release-note
None
```


ti-chi-bot: [REVIEW NOTIFICATION]

This pull request has not been approved.


To complete the [pull request process](https://book.prow.tidb.net/#/en/workflows/pr), please ask the reviewers in the [list](https://prow.tidb.net/tichi/repos/tikv/pd/pulls/5628/owners) to review by filling `/cc @reviewer` in the comment.
After your PR has acquired the required number of LGTMs, you can assign this pull request to the committer in the [list](https://prow.tidb.net/tichi/repos/tikv/pd/pulls/5628/owners) by filling  `/assign @committer` in the comment to help you merge this pull request.

The full list of commands accepted by this bot can be found [here](https://prow.tidb.net/command-help?repo=tikv%2Fpd).

<details>

Reviewer can indicate their review by submitting an approval review.
Reviewer can cancel approval by submitting a request changes review.
</details>

<!--Review Notification Identifier-->
ti-chi-bot: 
[FORMAT CHECKER NOTIFICATION]

**Notice**: To remove the `do-not-merge/needs-linked-issue` label, please provide the linked issue number on one line in the PR body, for example: `Issue Number: close #123` or `Issue Number: ref #456`, multiple issues should use full syntax for each issue and be separated by a comma, like: `Issue Number: close #123, ref #456`.

<sub>:open_book: For more info, you can check the ["Linking issues"](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md#linking-issues) section in the [CONTRIBUTING.md](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md).</sub>


<!--Checker Notification Identifier-->

ti-chi-bot: 
[FORMAT CHECKER NOTIFICATION]

**Notice**: To remove the `do-not-merge/needs-linked-issue` label, please provide the linked issue number on one line in the PR body, for example: `Issue Number: close #123` or `Issue Number: ref #456`, multiple issues should use full syntax for each issue and be separated by a comma, like: `Issue Number: close #123, ref #456`.

<sub>:open_book: For more info, you can check the ["Linking issues"](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md#linking-issues) section in the [CONTRIBUTING.md](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md).</sub>


<!--Checker Notification Identifier-->

codecov[bot]: # [Codecov](https://codecov.io/gh/tikv/pd/pull/5628?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv) Report
Base: **75.66**% // Head: **75.68**% // Increases project coverage by **`+0.01%`** :tada:
> Coverage data is based on head [(`28fa121`)](https://codecov.io/gh/tikv/pd/pull/5628?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv) compared to base [(`ec8ff1a`)](https://codecov.io/gh/tikv/pd/commit/ec8ff1a0f426c340216ebe618367b319e5083aae?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #5628      +/-   ##
==========================================
+ Coverage   75.66%   75.68%   +0.01%     
==========================================
  Files         326      326              
  Lines       32370    32371       +1     
==========================================
+ Hits        24494    24499       +5     
+ Misses       5770     5760      -10     
- Partials     2106     2112       +6     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `75.68% <100.00%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/tikv/pd/pull/5628?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv) | Coverage Δ | |
|---|---|---|
| [pkg/rangetree/range\_tree.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-cGtnL3JhbmdldHJlZS9yYW5nZV90cmVlLmdv) | `98.33% <100.00%> (+0.02%)` | :arrow_up: |
| [server/core/region.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL2NvcmUvcmVnaW9uLmdv) | `91.85% <100.00%> (ø)` | |
| [server/core/region\_tree.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL2NvcmUvcmVnaW9uX3RyZWUuZ28=) | `94.16% <100.00%> (ø)` | |
| [pkg/errs/errs.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-cGtnL2VycnMvZXJycy5nbw==) | `75.00% <0.00%> (-25.00%)` | :arrow_down: |
| [server/storage/kv/etcd\_kv.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL3N0b3JhZ2Uva3YvZXRjZF9rdi5nbw==) | `79.71% <0.00%> (-5.80%)` | :arrow_down: |
| [server/election/leadership.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL2VsZWN0aW9uL2xlYWRlcnNoaXAuZ28=) | `73.19% <0.00%> (-5.16%)` | :arrow_down: |
| [server/member/member.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL21lbWJlci9tZW1iZXIuZ28=) | `62.10% <0.00%> (-3.69%)` | :arrow_down: |
| [server/encryptionkm/key\_manager.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL2VuY3J5cHRpb25rbS9rZXlfbWFuYWdlci5nbw==) | `70.11% <0.00%> (-1.60%)` | :arrow_down: |
| [server/server.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-c2VydmVyL3NlcnZlci5nbw==) | `74.43% <0.00%> (-1.40%)` | :arrow_down: |
| [pkg/btree/btree.go](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv#diff-cGtnL2J0cmVlL2J0cmVlLmdv) | `86.26% <0.00%> (-0.73%)` | :arrow_down: |
| ... and [16 more](https://codecov.io/gh/tikv/pd/pull/5628/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/tikv/pd/pull/5628?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tikv).

ti-chi-bot: 
[FORMAT CHECKER NOTIFICATION]

**Notice**: To remove the `do-not-merge/needs-linked-issue` label, please provide the linked issue number on one line in the PR body, for example: `Issue Number: close #123` or `Issue Number: ref #456`, multiple issues should use full syntax for each issue and be separated by a comma, like: `Issue Number: close #123, ref #456`.

<sub>:open_book: For more info, you can check the ["Linking issues"](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md#linking-issues) section in the [CONTRIBUTING.md](https://github.com/tikv/tikv/blob/master/CONTRIBUTING.md).</sub>


<!--Checker Notification Identifier-->

nolouch: /merge
ti-chi-bot: @nolouch: It seems you want to merge this PR, I will help you trigger all the tests:

/run-all-tests


<details>

Instructions for interacting with me using PR comments are available [here](https://prow.tidb.net/command-help).  If you have questions or suggestions related to my behavior, please file an issue against the [ti-community-infra/tichi](https://github.com/ti-community-infra/tichi/issues/new?title=Prow%20issue:) repository.
</details>
ti-chi-bot: This pull request has been accepted and is ready to merge. <details>Commit hash: 1445eca71a4954b8d948f402588296ec1998d94f</details>
ti-chi-bot: @rleungx: Your PR was out of date, I have automatically updated it for you.

At the same time I will also trigger all tests for you:

/run-all-tests

If the CI test fails, you just re-trigger the test that failed and the bot will merge the PR for you after the CI passes.


<details>

Instructions for interacting with me using PR comments are available [here](https://prow.tidb.net/command-help).  If you have questions or suggestions related to my behavior, please file an issue against the [ti-community-infra/tichi](https://github.com/ti-community-infra/tichi/issues/new?title=Prow%20issue:) repository.
</details>

Patch:
diff --git a/pkg/rangetree/range_tree.go b/pkg/rangetree/range_tree.go
index 47d7e960a..174e338f7 100644
--- a/pkg/rangetree/range_tree.go
+++ b/pkg/rangetree/range_tree.go
@@ -76,9 +76,10 @@ func (r *RangeTree) GetOverlaps(item RangeItem) []RangeItem {
 	}
 
 	var overlaps []RangeItem
+	endKey := item.GetEndKey()
 	r.tree.AscendGreaterOrEqual(result, func(i btree.Item) bool {
 		over := i.(RangeItem)
-		if len(item.GetEndKey()) > 0 && bytes.Compare(item.GetEndKey(), over.GetStartKey()) <= 0 {
+		if len(endKey) > 0 && bytes.Compare(endKey, over.GetStartKey()) <= 0 {
 			return false
 		}
 		overlaps = append(overlaps, over)
diff --git a/server/core/region.go b/server/core/region.go
index d041ede2c..cdf961749 100644
--- a/server/core/region.go
+++ b/server/core/region.go
@@ -702,7 +702,7 @@ func (rm regionMap) Get(id uint64) *regionItem {
 // If the regionItem already exists, it will be overwritten.
 // Note: Do not use this function when you only need to update the RegionInfo and do not need a new regionItem.
 func (rm regionMap) AddNew(region *RegionInfo) *regionItem {
-	item := &regionItem{region: region}
+	item := &regionItem{RegionInfo: region}
 	rm[region.GetID()] = item
 	return item
 }
@@ -738,7 +738,7 @@ func NewRegionsInfo() *RegionsInfo {
 // GetRegion returns the RegionInfo with regionID
 func (r *RegionsInfo) GetRegion(regionID uint64) *RegionInfo {
 	if item := r.regions.Get(regionID); item != nil {
-		return item.region
+		return item.RegionInfo
 	}
 	return nil
 }
@@ -750,7 +750,7 @@ func (r *RegionsInfo) SetRegion(region *RegionInfo) (overlaps []*RegionInfo) {
 	rangeChanged := true // This Region is new, or its range has changed.
 	if item = r.regions.Get(region.GetID()); item != nil {
 		// If this ID already exists, use the existing regionItem and pick out the origin.
-		origin := item.region
+		origin := item.RegionInfo
 		rangeChanged = !origin.rangeEqualsTo(region)
 		if rangeChanged {
 			// Delete itself in regionTree so that overlaps will not contain itself.
@@ -765,14 +765,14 @@ func (r *RegionsInfo) SetRegion(region *RegionInfo) (overlaps []*RegionInfo) {
 			// If the peers are not changed, only the statistical on the sub regionTree needs to be updated.
 			r.updateSubTreeStat(origin, region)
 			// Update the RegionInfo in the regionItem.
-			item.region = region
+			item.RegionInfo = region
 			return
 		}
 		// If the range or peers have changed, the sub regionTree needs to be cleaned up.
 		// TODO: Improve performance by deleting only the different peers.
 		r.removeRegionFromSubTree(origin)
 		// Update the RegionInfo in the regionItem.
-		item.region = region
+		item.RegionInfo = region
 	} else {
 		// If this ID does not exist, generate a new regionItem and save it in the regionMap.
 		item = r.regions.AddNew(region)
@@ -963,7 +963,7 @@ func (r *RegionsInfo) GetPrevRegionByKey(regionKey []byte) *RegionInfo {
 func (r *RegionsInfo) GetRegions() []*RegionInfo {
 	regions := make([]*RegionInfo, 0, r.regions.Len())
 	for _, item := range r.regions {
-		regions = append(regions, item.region)
+		regions = append(regions, item.RegionInfo)
 	}
 	return regions
 }
@@ -1027,7 +1027,7 @@ func (r *RegionsInfo) GetStoreWriteRate(storeID uint64) (bytesRate, keysRate flo
 func (r *RegionsInfo) GetMetaRegions() []*metapb.Region {
 	regions := make([]*metapb.Region, 0, r.regions.Len())
 	for _, item := range r.regions {
-		regions = append(regions, typeutil.DeepClone(item.region.meta, RegionFactory))
+		regions = append(regions, typeutil.DeepClone(item.meta, RegionFactory))
 	}
 	return regions
 }
@@ -1110,7 +1110,7 @@ func (r *RegionsInfo) RandLearnerRegions(storeID uint64, ranges []KeyRange, n in
 // GetLeader returns leader RegionInfo by storeID and regionID (now only used in test)
 func (r *RegionsInfo) GetLeader(storeID uint64, region *RegionInfo) *RegionInfo {
 	if leaders, ok := r.leaders[storeID]; ok {
-		return leaders.find(region).region
+		return leaders.find(region).RegionInfo
 	}
 	return nil
 }
@@ -1118,7 +1118,7 @@ func (r *RegionsInfo) GetLeader(storeID uint64, region *RegionInfo) *RegionInfo
 // GetFollower returns follower RegionInfo by storeID and regionID (now only used in test)
 func (r *RegionsInfo) GetFollower(storeID uint64, region *RegionInfo) *RegionInfo {
 	if followers, ok := r.followers[storeID]; ok {
-		return followers.find(region).region
+		return followers.find(region).RegionInfo
 	}
 	return nil
 }
@@ -1215,11 +1215,11 @@ func (r *RegionsInfo) GetAdjacentRegions(region *RegionInfo) (*RegionInfo, *Regi
 	p, n := r.tree.getAdjacentRegions(region)
 	var prev, next *RegionInfo
 	// check key to avoid key range hole
-	if p != nil && bytes.Equal(p.region.GetEndKey(), region.GetStartKey()) {
-		prev = r.GetRegion(p.region.GetID())
+	if p != nil && bytes.Equal(p.GetEndKey(), region.GetStartKey()) {
+		prev = r.GetRegion(p.GetID())
 	}
-	if n != nil && bytes.Equal(region.GetEndKey(), n.region.GetStartKey()) {
-		next = r.GetRegion(n.region.GetID())
+	if n != nil && bytes.Equal(region.GetEndKey(), n.GetStartKey()) {
+		next = r.GetRegion(n.GetID())
 	}
 	return prev, next
 }
diff --git a/server/core/region_tree.go b/server/core/region_tree.go
index a5d717a93..690566758 100644
--- a/server/core/region_tree.go
+++ b/server/core/region_tree.go
@@ -30,28 +30,28 @@ import (
 var _ rangetree.RangeItem = &regionItem{}
 
 type regionItem struct {
-	region *RegionInfo
+	*RegionInfo
 }
 
 // GetStartKey returns the start key of the region.
 func (r *regionItem) GetStartKey() []byte {
-	return r.region.GetStartKey()
+	return r.meta.StartKey
 }
 
 // GetEndKey returns the end key of the region.
 func (r *regionItem) GetEndKey() []byte {
-	return r.region.GetEndKey()
+	return r.meta.EndKey
 }
 
 // Less returns true if the region start key is less than the other.
 func (r *regionItem) Less(other btree.Item) bool {
-	left := r.region.GetStartKey()
-	right := other.(rangetree.RangeItem).GetStartKey()
+	left := r.meta.StartKey
+	right := other.(*regionItem).meta.StartKey
 	return bytes.Compare(left, right) < 0
 }
 
 func (r *regionItem) Contains(key []byte) bool {
-	start, end := r.region.GetStartKey(), r.region.GetEndKey()
+	start, end := r.GetStartKey(), r.GetEndKey()
 	return bytes.Compare(key, start) >= 0 && (len(end) == 0 || bytes.Compare(key, end) < 0)
 }
 
@@ -88,11 +88,11 @@ func (t *regionTree) length() int {
 
 // getOverlaps gets the regions which are overlapped with the specified region range.
 func (t *regionTree) getOverlaps(region *RegionInfo) []*RegionInfo {
-	item := &regionItem{region: region}
+	item := &regionItem{RegionInfo: region}
 	result := t.tree.GetOverlaps(item)
 	overlaps := make([]*RegionInfo, len(result))
 	for i, r := range result {
-		overlaps[i] = r.(*regionItem).region
+		overlaps[i] = r.(*regionItem).RegionInfo
 	}
 	return overlaps
 }
@@ -101,7 +101,7 @@ func (t *regionTree) getOverlaps(region *RegionInfo) []*RegionInfo {
 // It finds and deletes all the overlapped regions first, and then
 // insert the region.
 func (t *regionTree) update(item *regionItem) []*RegionInfo {
-	region := item.region
+	region := item.RegionInfo
 	t.totalSize += region.approximateSize
 	regionWriteBytesRate, regionWriteKeysRate := region.GetWriteRate()
 	t.totalWriteBytesRate += regionWriteBytesRate
@@ -110,7 +110,7 @@ func (t *regionTree) update(item *regionItem) []*RegionInfo {
 	overlaps := t.tree.Update(item)
 	result := make([]*RegionInfo, len(overlaps))
 	for i, overlap := range overlaps {
-		old := overlap.(*regionItem).region
+		old := overlap.(*regionItem).RegionInfo
 		result[i] = old
 		log.Debug("overlapping region",
 			zap.Uint64("region-id", old.GetID()),
@@ -125,7 +125,7 @@ func (t *regionTree) update(item *regionItem) []*RegionInfo {
 	return result
 }
 
-// updateStat is used to update statistics when regionItem.region is directly replaced.
+// updateStat is used to update statistics when regionItem.RegionInfo is directly replaced.
 func (t *regionTree) updateStat(origin *RegionInfo, region *RegionInfo) {
 	t.totalSize += region.approximateSize
 	regionWriteBytesRate, regionWriteKeysRate := region.GetWriteRate()
@@ -145,14 +145,14 @@ func (t *regionTree) remove(region *RegionInfo) {
 	if t.length() == 0 {
 		return
 	}
-	item := &regionItem{region: region}
+	item := &regionItem{RegionInfo: region}
 	result := t.tree.Find(item)
-	if result == nil || result.(*regionItem).region.GetID() != region.GetID() {
+	if result == nil || result.(*regionItem).GetID() != region.GetID() {
 		return
 	}
 
-	t.totalSize -= result.(*regionItem).region.GetApproximateSize()
-	regionWriteBytesRate, regionWriteKeysRate := result.(*regionItem).region.GetWriteRate()
+	t.totalSize -= result.(*regionItem).GetApproximateSize()
+	regionWriteBytesRate, regionWriteKeysRate := result.(*regionItem).GetWriteRate()
 	t.totalWriteBytesRate -= regionWriteBytesRate
 	t.totalWriteKeysRate -= regionWriteKeysRate
 	t.tree.Remove(result)
@@ -165,7 +165,7 @@ func (t *regionTree) search(regionKey []byte) *RegionInfo {
 	if result == nil {
 		return nil
 	}
-	return result.region
+	return result.RegionInfo
 }
 
 // searchPrev returns the previous region of the region where the regionKey is located.
@@ -175,20 +175,20 @@ func (t *regionTree) searchPrev(regionKey []byte) *RegionInfo {
 	if curRegionItem == nil {
 		return nil
 	}
-	prevRegionItem, _ := t.getAdjacentRegions(curRegionItem.region)
+	prevRegionItem, _ := t.getAdjacentRegions(curRegionItem.RegionInfo)
 	if prevRegionItem == nil {
 		return nil
 	}
-	if !bytes.Equal(prevRegionItem.region.GetEndKey(), curRegionItem.region.GetStartKey()) {
+	if !bytes.Equal(prevRegionItem.GetEndKey(), curRegionItem.GetStartKey()) {
 		return nil
 	}
-	return prevRegionItem.region
+	return prevRegionItem.RegionInfo
 }
 
 // find is a helper function to find an item that contains the regions start
 // key.
 func (t *regionTree) find(region *RegionInfo) *regionItem {
-	item := t.tree.Find(&regionItem{region: region})
+	item := t.tree.Find(&regionItem{RegionInfo: region})
 	if item == nil {
 		return nil
 	}
@@ -205,9 +205,9 @@ func (t *regionTree) scanRange(startKey []byte, f func(*RegionInfo) bool) {
 	// find if there is a region with key range [s, d), s < startKey < d
 	fn := func(item rangetree.RangeItem) bool {
 		r := item.(*regionItem)
-		return f(r.region)
+		return f(r.RegionInfo)
 	}
-	t.tree.ScanRange(&regionItem{region: region}, fn)
+	t.tree.ScanRange(&regionItem{RegionInfo: region}, fn)
 }
 
 func (t *regionTree) scanRanges() []*RegionInfo {
@@ -223,7 +223,7 @@ func (t *regionTree) scanRanges() []*RegionInfo {
 }
 
 func (t *regionTree) getAdjacentRegions(region *RegionInfo) (*regionItem, *regionItem) {
-	item := &regionItem{region: &RegionInfo{meta: &metapb.Region{StartKey: region.GetStartKey()}}}
+	item := &regionItem{RegionInfo: &RegionInfo{meta: &metapb.Region{StartKey: region.GetStartKey()}}}
 	prevItem, nextItem := t.tree.GetAdjacentItem(item)
 	var prev, next *regionItem
 	if prevItem != nil {
@@ -248,10 +248,10 @@ func (t *regionTree) RandomRegion(ranges []KeyRange) *RegionInfo {
 	for _, i := range rand.Perm(len(ranges)) {
 		var endIndex int
 		startKey, endKey := ranges[i].StartKey, ranges[i].EndKey
-		startRegion, startIndex := t.tree.GetWithIndex(&regionItem{region: &RegionInfo{meta: &metapb.Region{StartKey: startKey}}})
+		startRegion, startIndex := t.tree.GetWithIndex(&regionItem{RegionInfo: &RegionInfo{meta: &metapb.Region{StartKey: startKey}}})
 
 		if len(endKey) != 0 {
-			_, endIndex = t.tree.GetWithIndex(&regionItem{region: &RegionInfo{meta: &metapb.Region{StartKey: endKey}}})
+			_, endIndex = t.tree.GetWithIndex(&regionItem{RegionInfo: &RegionInfo{meta: &metapb.Region{StartKey: endKey}}})
 		} else {
 			endIndex = t.tree.Len()
 		}
@@ -272,7 +272,7 @@ func (t *regionTree) RandomRegion(ranges []KeyRange) *RegionInfo {
 			continue
 		}
 		index := rand.Intn(endIndex-startIndex) + startIndex
-		region := t.tree.GetAt(index).(*regionItem).region
+		region := t.tree.GetAt(index).(*regionItem).RegionInfo
 		if region.isInvolved(startKey, endKey) {
 			return region
 		}


Test patch:
diff --git a/server/core/region_test.go b/server/core/region_test.go
index f3f0c917a..93367f8db 100644
--- a/server/core/region_test.go
+++ b/server/core/region_test.go
@@ -401,7 +401,7 @@ func regionInfo(id uint64) *RegionInfo {
 func check(re *require.Assertions, rm regionMap, ids ...uint64) {
 	// Check Get.
 	for _, id := range ids {
-		re.Equal(id, rm.Get(id).region.GetID())
+		re.Equal(id, rm.Get(id).GetID())
 	}
 	// Check Len.
 	re.Equal(len(ids), rm.Len())
@@ -412,7 +412,7 @@ func check(re *require.Assertions, rm regionMap, ids ...uint64) {
 	}
 	set1 := make(map[uint64]struct{})
 	for _, r := range rm {
-		set1[r.region.GetID()] = struct{}{}
+		set1[r.GetID()] = struct{}{}
 	}
 	re.Equal(expect, set1)
 }
diff --git a/server/core/region_tree_test.go b/server/core/region_tree_test.go
index a8a8d6a3b..3237a5daf 100644
--- a/server/core/region_tree_test.go
+++ b/server/core/region_tree_test.go
@@ -185,28 +185,28 @@ func TestRegionTree(t *testing.T) {
 	// check get adjacent regions
 	prev, next := tree.getAdjacentRegions(regionA)
 	re.Nil(prev)
-	re.Equal(regionB, next.region)
+	re.Equal(regionB, next.RegionInfo)
 	prev, next = tree.getAdjacentRegions(regionB)
-	re.Equal(regionA, prev.region)
-	re.Equal(regionD, next.region)
+	re.Equal(regionA, prev.RegionInfo)
+	re.Equal(regionD, next.RegionInfo)
 	prev, next = tree.getAdjacentRegions(regionC)
-	re.Equal(regionB, prev.region)
-	re.Equal(regionD, next.region)
+	re.Equal(regionB, prev.RegionInfo)
+	re.Equal(regionD, next.RegionInfo)
 	prev, next = tree.getAdjacentRegions(regionD)
-	re.Equal(regionB, prev.region)
+	re.Equal(regionB, prev.RegionInfo)
 	re.Nil(next)
 
 	// region with the same range and different region id will not be delete.
-	region0 := newRegionItem([]byte{}, []byte("a")).region
+	region0 := newRegionItem([]byte{}, []byte("a")).RegionInfo
 	updateNewItem(tree, region0)
 	re.Equal(region0, tree.search([]byte{}))
-	anotherRegion0 := newRegionItem([]byte{}, []byte("a")).region
+	anotherRegion0 := newRegionItem([]byte{}, []byte("a")).RegionInfo
 	anotherRegion0.meta.Id = 123
 	tree.remove(anotherRegion0)
 	re.Equal(region0, tree.search([]byte{}))
 
 	// overlaps with 0, A, B, C.
-	region0D := newRegionItem([]byte(""), []byte("d")).region
+	region0D := newRegionItem([]byte(""), []byte("d")).RegionInfo
 	updateNewItem(tree, region0D)
 	re.Equal(region0D, tree.search([]byte{}))
 	re.Equal(region0D, tree.search([]byte("a")))
@@ -215,7 +215,7 @@ func TestRegionTree(t *testing.T) {
 	re.Equal(regionD, tree.search([]byte("d")))
 
 	// overlaps with D.
-	regionE := newRegionItem([]byte("e"), []byte{}).region
+	regionE := newRegionItem([]byte("e"), []byte{}).RegionInfo
 	updateNewItem(tree, regionE)
 	re.Equal(region0D, tree.search([]byte{}))
 	re.Equal(region0D, tree.search([]byte("a")))
@@ -240,7 +240,7 @@ func updateRegions(re *require.Assertions, tree *regionTree, regions []*RegionIn
 func TestRegionTreeSplitAndMerge(t *testing.T) {
 	re := require.New(t)
 	tree := newRegionTree()
-	regions := []*RegionInfo{newRegionItem([]byte{}, []byte{}).region}
+	regions := []*RegionInfo{newRegionItem([]byte{}, []byte{}).RegionInfo}
 
 	// Byte will underflow/overflow if n > 7.
 	n := 7
@@ -355,7 +355,7 @@ func TestRandomRegionDiscontinuous(t *testing.T) {
 }
 
 func updateNewItem(tree *regionTree, region *RegionInfo) {
-	item := &regionItem{region: region}
+	item := &regionItem{RegionInfo: region}
 	tree.update(item)
 }
 
@@ -379,7 +379,7 @@ func checkRandomRegion(re *require.Assertions, tree *regionTree, regions []*Regi
 }
 
 func newRegionItem(start, end []byte) *regionItem {
-	return &regionItem{region: NewTestRegionInfo(start, end)}
+	return &regionItem{RegionInfo: NewTestRegionInfo(start, end)}
 }
 
 type mockRegionTreeData struct {