Skip to content

Commit c839b90

Browse files
committed
mmaprototype: move MMARebalanceAdvisor to rebalance_advisor.go
This commit moves `MMARebalanceAdvisor` related code from `allocator_state.go` to `rebalance_advisor.go`.
1 parent 53cf835 commit c839b90

File tree

3 files changed

+113
-99
lines changed

3 files changed

+113
-99
lines changed

pkg/kv/kvserver/allocator/mmaprototype/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ go_library(
1212
"load.go",
1313
"memo_helper.go",
1414
"messages.go",
15+
"rebalance_advisor.go",
1516
"top_k_replicas.go",
1617
],
1718
importpath = "github.com/cockroachdb/cockroach/pkg/kv/kvserver/allocator/mmaprototype",

pkg/kv/kvserver/allocator/mmaprototype/allocator_state.go

Lines changed: 0 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,105 +1295,6 @@ func (a *allocatorState) ensureAnalyzedConstraints(rstate *rangeState) bool {
12951295
return true
12961296
}
12971297

1298-
// MMARebalanceAdvisor contains information that mma needs to determine if a
1299-
// candidate is in conflict with its goals. All fields should be immutable after
1300-
// its initialization.
1301-
//
1302-
// MMARebalanceAdvisor uses the meansLoad summary to compute the load summary
1303-
// for a provided candidate. Then it compares the candidate load summary against
1304-
// the existingStoreSLS to determine if the candidate is more overloaded than
1305-
// the existing store. If yes, mma will return true for IsInConflictWithMMA. It
1306-
// is up to the caller to decide what to do with this information.
1307-
type MMARebalanceAdvisor struct {
1308-
// disabled is true when MMA is disabled. It overrides all decisions with
1309-
// IsInConflictWithMMA returning false.
1310-
disabled bool
1311-
// existingStoreID is the ID of the existing store.
1312-
existingStoreID roachpb.StoreID
1313-
// existingStoreSLS holds the load summary for the existing store. It is
1314-
// initially nil and is computed using existingStoreID and means the first
1315-
// time IsInConflictWithMMA is called. The caller must ensure this advisor is
1316-
// only used with the corresponding existingStoreID.
1317-
existingStoreSLS *storeLoadSummary
1318-
// means is the means for the candidate set.
1319-
means meansLoad
1320-
}
1321-
1322-
// NoopMMARebalanceAdvisor is a no-op MMARebalanceAdvisor that always returns
1323-
// false for IsInConflictWithMMA. Used when MMA is disabled or mma does not have
1324-
// enough information to determine.
1325-
func NoopMMARebalanceAdvisor() *MMARebalanceAdvisor {
1326-
return &MMARebalanceAdvisor{
1327-
disabled: true,
1328-
}
1329-
}
1330-
1331-
// BuildMMARebalanceAdvisor constructs an MMARebalanceAdvisor for the given
1332-
// existing store and candidate stores. The advisor can be used to determine if
1333-
// a candidate is in conflict with the existing store via IsInConflictWithMMA.
1334-
// The provided cands list may or may not include the existing store. This
1335-
// method always adds the existing store to the cands list so that it is
1336-
// included in the mean calculation. It is up to computeMeansForStoreSet to
1337-
// handle the de-duplication of storeIDs from the cands list.
1338-
func (a *allocatorState) BuildMMARebalanceAdvisor(
1339-
existing roachpb.StoreID, cands []roachpb.StoreID,
1340-
) *MMARebalanceAdvisor {
1341-
// TODO(wenyihu6): for simplicity, we create a new scratchNodes every call.
1342-
// We should reuse the scratchNodes instead.
1343-
scratchNodes := map[roachpb.NodeID]*NodeLoad{}
1344-
scratchStores := map[roachpb.StoreID]struct{}{}
1345-
cands = append(cands, existing)
1346-
means := computeMeansForStoreSet(a.cs, cands, scratchNodes, scratchStores)
1347-
return &MMARebalanceAdvisor{
1348-
existingStoreID: existing,
1349-
means: means,
1350-
}
1351-
}
1352-
1353-
// IsInConflictWithMMA determines if the given candidate is in conflict with the
1354-
// existing store using the provided MMARebalanceAdvisor. For simplicity, we
1355-
// currently say that this is in conflict if the candidate is more overloaded
1356-
// than the existing store. This is subject to change in the future. Caller is
1357-
// responsible for making sure the MMARebalanceAdvisor is for the correct
1358-
// existing store and candidate set.
1359-
func (a *allocatorState) IsInConflictWithMMA(
1360-
ctx context.Context, cand roachpb.StoreID, advisor *MMARebalanceAdvisor, cpuOnly bool,
1361-
) bool {
1362-
if advisor.disabled {
1363-
return false
1364-
}
1365-
// Lazily compute and cache the load summary for the existing store.
1366-
if advisor.existingStoreSLS == nil {
1367-
summary := a.cs.computeLoadSummary(ctx, advisor.existingStoreID, &advisor.means.storeLoad, &advisor.means.nodeLoad)
1368-
advisor.existingStoreSLS = &summary
1369-
}
1370-
existingSLS := advisor.existingStoreSLS
1371-
// Always compute the candidate's load summary.
1372-
candSLS := a.cs.computeLoadSummary(ctx, cand, &advisor.means.storeLoad, &advisor.means.nodeLoad)
1373-
1374-
var conflict bool
1375-
if cpuOnly {
1376-
conflict = candSLS.dimSummary[CPURate] > existingSLS.dimSummary[CPURate]
1377-
if conflict {
1378-
log.KvDistribution.VEventf(
1379-
ctx, 2,
1380-
"mma rejected candidate s%d(cpu-only) as a replacement for s%d: candidate=%v > existing=%v",
1381-
cand, advisor.existingStoreID, candSLS.dimSummary[CPURate], existingSLS.dimSummary[CPURate],
1382-
)
1383-
}
1384-
} else {
1385-
conflict = candSLS.sls > existingSLS.sls
1386-
if conflict {
1387-
log.KvDistribution.VEventf(
1388-
ctx, 2,
1389-
"mma rejected candidate s%d as a replacement for s%d: candidate=%v > existing=%v",
1390-
cand, advisor.existingStoreID, candSLS.sls, existingSLS.sls,
1391-
)
1392-
}
1393-
}
1394-
return conflict
1395-
}
1396-
13971298
// Consider the core logic for a change, rebalancing or recovery.
13981299
//
13991300
// - There is a constraint expression for the target: constraintDisj
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package mmaprototype
7+
8+
import (
9+
"context"
10+
11+
"github.com/cockroachdb/cockroach/pkg/roachpb"
12+
"github.com/cockroachdb/cockroach/pkg/util/log"
13+
)
14+
15+
// MMARebalanceAdvisor contains information that mma needs to determine if a
16+
// candidate is in conflict with its goals. All fields should be immutable after
17+
// its initialization.
18+
//
19+
// MMARebalanceAdvisor uses the meansLoad summary to compute the load summary
20+
// for a provided candidate. Then it compares the candidate load summary against
21+
// the existingStoreSLS to determine if the candidate is more overloaded than
22+
// the existing store. If yes, mma will return true for IsInConflictWithMMA. It
23+
// is up to the caller to decide what to do with this information.
24+
type MMARebalanceAdvisor struct {
25+
// disabled is true when MMA is disabled. It overrides all decisions with
26+
// IsInConflictWithMMA returning false.
27+
disabled bool
28+
// existingStoreID is the ID of the existing store.
29+
existingStoreID roachpb.StoreID
30+
// existingStoreSLS holds the load summary for the existing store. It is
31+
// initially nil and is computed using existingStoreID and means the first
32+
// time IsInConflictWithMMA is called. The caller must ensure this advisor is
33+
// only used with the corresponding existingStoreID.
34+
existingStoreSLS *storeLoadSummary
35+
// means is the means for the candidate set.
36+
means meansLoad
37+
}
38+
39+
// NoopMMARebalanceAdvisor is a no-op MMARebalanceAdvisor that always returns
40+
// false for IsInConflictWithMMA. Used when MMA is disabled or mma does not have
41+
// enough information to determine.
42+
func NoopMMARebalanceAdvisor() *MMARebalanceAdvisor {
43+
return &MMARebalanceAdvisor{
44+
disabled: true,
45+
}
46+
}
47+
48+
// BuildMMARebalanceAdvisor constructs an MMARebalanceAdvisor for the given
49+
// existing store and candidate stores. The advisor can be used to determine if
50+
// a candidate is in conflict with the existing store via IsInConflictWithMMA.
51+
// The provided cands list may or may not include the existing store. This
52+
// method always adds the existing store to the cands list so that it is
53+
// included in the mean calculation. It is up to computeMeansForStoreSet to
54+
// handle the de-duplication of storeIDs from the cands list.
55+
func (a *allocatorState) BuildMMARebalanceAdvisor(
56+
existing roachpb.StoreID, cands []roachpb.StoreID,
57+
) *MMARebalanceAdvisor {
58+
// TODO(wenyihu6): for simplicity, we create a new scratchNodes every call.
59+
// We should reuse the scratchNodes instead.
60+
scratchNodes := map[roachpb.NodeID]*NodeLoad{}
61+
scratchStores := map[roachpb.StoreID]struct{}{}
62+
cands = append(cands, existing)
63+
means := computeMeansForStoreSet(a.cs, cands, scratchNodes, scratchStores)
64+
return &MMARebalanceAdvisor{
65+
existingStoreID: existing,
66+
means: means,
67+
}
68+
}
69+
70+
// IsInConflictWithMMA determines if the given candidate is in conflict with the
71+
// existing store using the provided MMARebalanceAdvisor. For simplicity, we
72+
// currently say that this is in conflict if the candidate is more overloaded
73+
// than the existing store. This is subject to change in the future. Caller is
74+
// responsible for making sure the MMARebalanceAdvisor is for the correct
75+
// existing store and candidate set.
76+
func (a *allocatorState) IsInConflictWithMMA(
77+
ctx context.Context, cand roachpb.StoreID, advisor *MMARebalanceAdvisor, cpuOnly bool,
78+
) bool {
79+
if advisor.disabled {
80+
return false
81+
}
82+
// Lazily compute and cache the load summary for the existing store.
83+
if advisor.existingStoreSLS == nil {
84+
summary := a.cs.computeLoadSummary(ctx, advisor.existingStoreID, &advisor.means.storeLoad, &advisor.means.nodeLoad)
85+
advisor.existingStoreSLS = &summary
86+
}
87+
existingSLS := advisor.existingStoreSLS
88+
// Always compute the candidate's load summary.
89+
candSLS := a.cs.computeLoadSummary(ctx, cand, &advisor.means.storeLoad, &advisor.means.nodeLoad)
90+
91+
var conflict bool
92+
if cpuOnly {
93+
conflict = candSLS.dimSummary[CPURate] > existingSLS.dimSummary[CPURate]
94+
if conflict {
95+
log.KvDistribution.VEventf(
96+
ctx, 2,
97+
"mma rejected candidate s%d(cpu-only) as a replacement for s%d: candidate=%v > existing=%v",
98+
cand, advisor.existingStoreID, candSLS.dimSummary[CPURate], existingSLS.dimSummary[CPURate],
99+
)
100+
}
101+
} else {
102+
conflict = candSLS.sls > existingSLS.sls
103+
if conflict {
104+
log.KvDistribution.VEventf(
105+
ctx, 2,
106+
"mma rejected candidate s%d as a replacement for s%d: candidate=%v > existing=%v",
107+
cand, advisor.existingStoreID, candSLS.sls, existingSLS.sls,
108+
)
109+
}
110+
}
111+
return conflict
112+
}

0 commit comments

Comments
 (0)