From 62e51d6fc7ce5fc02679322a466189146fa78cfd Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Mon, 26 Jan 2026 11:36:47 -0800 Subject: [PATCH 01/10] add new test cases --- .../mb/advisor/domain_advisor_test.go | 290 ++++++++++++++++++ pkg/consts/resctrl.go | 1 + 2 files changed, 291 insertions(+) diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go index 6362a4214c..d38a26e8c4 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go @@ -510,6 +510,296 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }}, wantErr: false, }, + { + name: "same priority with not enough capacity", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), + 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": { + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, + "share-50": {2: 0, 5: 0}, + }}, + wantErr: false, + }, + { + name: "same priority with enough capacity", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), + 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": { + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": { + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 20_000, 3: 20_000}, + "machine-60": {1: 20_000, 4: 20_000}, + "share-50": {2: 8500, 5: 8500}, + }}, + wantErr: false, + }, } for _, tt := range tests { tt := tt diff --git a/pkg/consts/resctrl.go b/pkg/consts/resctrl.go index 8d54030ffe..7dd102fe30 100644 --- a/pkg/consts/resctrl.go +++ b/pkg/consts/resctrl.go @@ -22,6 +22,7 @@ const ( ResctrlGroupRoot = "/" ResctrlGroupDedicated = "dedicated" ResctrlGroupSystem = "system" + ResctrlGroupMachine = "machine" ResctrlGroupShare = "share" ResctrlGroupReclaim = "reclaim" From bd5327ba32dd404c8f7af473bc5680298ff1107f Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Wed, 28 Jan 2026 17:09:48 -0800 Subject: [PATCH 02/10] support same priority --- .../qrm-plugins/mb/advisor/advisor_helper.go | 71 ++- .../mb/advisor/distributor/types.go | 9 + .../qrm-plugins/mb/advisor/domain_advisor.go | 59 +- .../mb/advisor/domain_advisor_test.go | 538 +++++++++++++++++- .../qrm-plugins/mb/advisor/resource/types.go | 1 + 5 files changed, 647 insertions(+), 31 deletions(-) diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index f49182c72c..dfb61336d8 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -126,10 +126,77 @@ func getGroupIncomingInfo(capacity int, incomingStats monitor.GroupMBStats) *res CapacityInMB: capacity, } - result.GroupSorted = sortGroups(maps.Keys(incomingStats)) - result.GroupTotalUses = getUsedTotalByGroup(incomingStats) + groups, subGroups := preProcessGroupInfo(incomingStats) + result.GroupSorted = sortGroups(maps.Keys(groups)) + result.GroupTotalUses = getUsedTotalByGroup(groups) result.FreeInMB, result.GroupLimits = getLimitsByGroupSorted(capacity, result.GroupSorted, result.GroupTotalUses) result.ResourceState = resource.GetResourceState(capacity, result.FreeInMB) + result.SubGroups = subGroups + return result +} + +// groupByWeight extracts the common logic of grouping by weight +func groupByWeight[T any](stats map[string]T) map[int][]string { + groups := make(map[int][]string, len(stats)) + for group := range stats { + weight := getWeight(group) + groups[weight] = append(groups[weight], group) + } + return groups +} + +// preProcessGroupInfo combines groups with same priority together +func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, map[string][]string) { + groups := groupByWeight(stats) + + result := make(monitor.GroupMBStats) + subGroupsMap := make(map[string][]string) + + for weight, equivGroups := range groups { + if len(equivGroups) == 1 { + result[equivGroups[0]] = stats[equivGroups[0]] + continue + } + + newKey := fmt.Sprintf("combined-%d", weight) + subGroupsMap[newKey] = equivGroups + + combined := make(monitor.GroupMB) + for _, group := range equivGroups { + for id, stat := range stats[group] { + combined[id] = stat + } + } + result[newKey] = combined + } + + return result, subGroupsMap +} + +func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]monitor.MBInfo { + groups := groupByWeight(sumStats) + + result := make(map[string][]monitor.MBInfo) + + for weight, equivGroups := range groups { + if len(equivGroups) == 1 { + result[equivGroups[0]] = sumStats[equivGroups[0]] + continue + } + + newKey := fmt.Sprintf("combined-%d", weight) + sumList := make([]monitor.MBInfo, len(sumStats[equivGroups[0]])) + + for _, group := range equivGroups { + for id, stat := range sumStats[group] { + sumList[id].LocalMB += stat.LocalMB + sumList[id].RemoteMB += stat.RemoteMB + sumList[id].TotalMB += stat.TotalMB + } + } + result[newKey] = sumList + } + return result } diff --git a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go index 56ace05b0b..406f70fa2d 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go +++ b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go @@ -21,6 +21,7 @@ import "math" type Distributor interface { // Distribute distributes total mb into ccds by their relative weights Distribute(total int, weights map[int]int) map[int]int + GetMax() int } func New(min, max int) Distributor { @@ -65,6 +66,10 @@ func (l *linearBoundedDistributor) adjust(value int) int { return value } +func (l *linearBoundedDistributor) GetMax() int { + return l.max +} + func getPortion(total int, weight int, totalWeight int) int { if weight <= 0 || totalWeight <= 0 { return 0 @@ -88,3 +93,7 @@ func (l logarithmicBoundedDistributor) Distribute(total int, weights map[int]int } return l.inner.Distribute(total, logarithmicWeights) } + +func (l logarithmicBoundedDistributor) GetMax() int { + return l.inner.max +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go index 1a19eddf00..cf6d3571b6 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go @@ -19,6 +19,7 @@ package advisor import ( "context" "fmt" + "strings" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/sets" @@ -84,7 +85,8 @@ func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainS // for each group, based on incoming targets, decide what the outgoing targets are var groupedDomOutgoingTargets map[string][]int - groupedDomOutgoingTargets, err = d.deriveOutgoingTargets(ctx, domainsMon.OutgoingGroupSumStat, groupedDomIncomingTargets) + outgoingGroupSumStat := preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) + groupedDomOutgoingTargets, err = d.deriveOutgoingTargets(ctx, outgoingGroupSumStat, groupedDomIncomingTargets) if err != nil { return nil, errors.Wrap(err, "failed to get plan") } @@ -96,8 +98,7 @@ func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainS // leverage the current observed outgoing stats (and implicit previous outgoing mb) // to adjust th outgoing mb hopeful to reach the desired target - groupedDomOutgoings := domainsMon.OutgoingGroupSumStat - groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, groupedDomOutgoings, d.capPercent) + groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, outgoingGroupSumStat, d.capPercent) if klog.V(6).Enabled() { general.InfofV(6, "[mbm] [advisor] group-domain outgoing quotas: %s", stringify(groupedDomainOutgoingQuotas)) @@ -234,37 +235,63 @@ func (d *domainAdvisor) distributeToCCDs(_ context.Context, quotas map[string][]int, outgoingStat map[int]monitor.GroupMBStats, ) map[string]map[int]int { result := map[string]map[int]int{} + for group, domQuota := range quotas { - // each domain is treated independently for domID, domTotal := range domQuota { - ccdDistributions := d.domainDistributeGroup(domID, group, domTotal, outgoingStat) - if len(ccdDistributions) == 0 { - continue + outgoings, subGroups := preProcessGroupInfo(outgoingStat[domID]) + + // Determine which groups to distribute + var groupsToDistribute []string + if strings.Contains(group, "combined-") { + groupsToDistribute = subGroups[group] + } else { + groupsToDistribute = []string{group} } - if _, ok := result[group]; !ok { - result[group] = make(map[int]int) - } - for ccd, v := range ccdDistributions { - result[group][ccd] = v + // Distribute for each group + for _, targetGroup := range groupsToDistribute { + ccdDistributions := d.domainDistributeGroup(domID, group, targetGroup, domTotal, outgoingStat, outgoings) + if len(ccdDistributions) == 0 { + continue + } + + // Accumulate results + if _, ok := result[targetGroup]; !ok { + result[targetGroup] = make(map[int]int) + } + for ccd, v := range ccdDistributions { + result[targetGroup][ccd] = v + } } } } + return result } -func (d *domainAdvisor) domainDistributeGroup(domID int, group string, - domTotal int, outgoingStat map[int]monitor.GroupMBStats, +func (d *domainAdvisor) domainDistributeGroup(domID int, group string, subGroup string, + domTotal int, outgoingStat map[int]monitor.GroupMBStats, outgoings monitor.GroupMBStats, ) map[int]int { weights := map[int]int{} - groupStat := outgoingStat[domID][group] + groupStat := outgoingStat[domID][subGroup] + if group != subGroup { + groupStat = outgoings[group] + } + totalMBSum := 0 for ccd, stat := range groupStat { weights[ccd] = stat.TotalMB + totalMBSum += stat.TotalMB } domCCDQuotas := d.ccdDistribute.Distribute(domTotal, weights) result := map[int]int{} for ccd, v := range domCCDQuotas { - result[ccd] = v + if _, ok := outgoingStat[domID][subGroup][ccd]; ok { + if totalMBSum < domTotal && group != subGroup { + result[ccd] = d.ccdDistribute.GetMax() + continue + } + result[ccd] = v + } } return result } diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go index d38a26e8c4..52d5b12b72 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go @@ -170,6 +170,7 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { "share-50": 10_000 - 2_200, }, ResourceState: resource.State("fit"), + SubGroups: map[string][]string{}, }, }, wantErr: false, @@ -216,7 +217,8 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { "share-60": 6_000, "share-50": 6_000 - 2_200, }, - ResourceState: resource.State("stressful"), + ResourceState: resource.State("underStress"), + SubGroups: map[string][]string{}, }, }, wantErr: false, @@ -511,7 +513,167 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { wantErr: false, }, { - name: "same priority with not enough capacity", + name: "same priority with not enough capacity for two and a higher priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), + 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 4250, 3: 4250}, + "machine-60": {1: 4250, 4: 4250}, + "/-100": {2: 20_000, 5: 20_000}, + }}, + wantErr: false, + }, + { + name: "same priority with not enough capacity for two and a lower priority", fields: fields{ domains: domain.Domains{ 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), @@ -601,21 +763,21 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, 1: { "dedicated-60": map[int]monitor.MBInfo{ - 0: { + 3: { LocalMB: 10_000, RemoteMB: 10_000, TotalMB: 20_000, }, }, "machine-60": map[int]monitor.MBInfo{ - 1: { + 4: { LocalMB: 10_000, RemoteMB: 10_000, TotalMB: 20_000, }, }, "share-50": map[int]monitor.MBInfo{ - 2: { + 5: { LocalMB: 10_000, RemoteMB: 0, TotalMB: 10_000, @@ -630,8 +792,18 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { RemoteMB: 10_000, TotalMB: 20_000, }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, }, "machine-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, 1: { LocalMB: 10_000, RemoteMB: 10_000, @@ -639,7 +811,12 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, }, "share-50": { - 2: { + 0: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + 1: { LocalMB: 10_000, RemoteMB: 0, TotalMB: 10_000, @@ -649,14 +826,174 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, }, want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, + "dedicated-60": {0: 14_250, 3: 14_250}, + "machine-60": {1: 14_250, 4: 14_250}, "share-50": {2: 0, 5: 0}, }}, wantErr: false, }, { - name: "same priority with enough capacity", + name: "same priority with not enough capacity for one and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), + 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": { + 0: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 14_250, 3: 14_250}, + "machine-60": {1: 14_250, 4: 14_250}, + "share-50": {2: 0, 5: 0}, + }}, + wantErr: false, + }, + { + name: "same priority with partial enough capacity and a lower priority", fields: fields{ domains: domain.Domains{ 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), @@ -746,21 +1083,21 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, 1: { "dedicated-60": map[int]monitor.MBInfo{ - 0: { + 3: { LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000, }, }, "machine-60": map[int]monitor.MBInfo{ - 1: { + 4: { LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000, }, }, "share-50": map[int]monitor.MBInfo{ - 2: { + 5: { LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000, @@ -775,8 +1112,18 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { RemoteMB: 5_000, TotalMB: 10_000, }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, }, "machine-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, 1: { LocalMB: 5_000, RemoteMB: 5_000, @@ -784,7 +1131,12 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, }, "share-50": { - 2: { + 0: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + 1: { LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000, @@ -800,6 +1152,166 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }}, wantErr: false, }, + { + name: "same priority with fully enough capacity and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), + 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": { + 0: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 20_000, 3: 20_000}, + "machine-60": {1: 20_000, 4: 20_000}, + "share-50": {2: 10_000, 5: 10_000}, + }}, + wantErr: false, + }, } for _, tt := range tests { tt := tt diff --git a/pkg/agent/qrm-plugins/mb/advisor/resource/types.go b/pkg/agent/qrm-plugins/mb/advisor/resource/types.go index 84166f086f..bd210cc60d 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/resource/types.go +++ b/pkg/agent/qrm-plugins/mb/advisor/resource/types.go @@ -55,4 +55,5 @@ type MBGroupIncomingStat struct { ResourceState State GroupLimits GroupSettings GroupSorted []sets.String + SubGroups map[string][]string } From 016317a42de97c8ffa96ca9e3bee52558ee76056 Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Mon, 2 Feb 2026 21:32:25 -0800 Subject: [PATCH 03/10] refactor --- pkg/agent/qrm-plugins/mb/advisor/advisor.go | 86 +++++++++++++++++++ .../qrm-plugins/mb/advisor/domain_advisor.go | 61 ++++--------- .../mb/advisor/domain_advisor_test.go | 31 +++---- pkg/agent/qrm-plugins/mb/policy/plugin.go | 2 +- 4 files changed, 120 insertions(+), 60 deletions(-) create mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor.go diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor.go b/pkg/agent/qrm-plugins/mb/advisor/advisor.go new file mode 100644 index 0000000000..1ac4fb46f7 --- /dev/null +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor.go @@ -0,0 +1,86 @@ +package advisor + +import ( + "context" + "strings" + + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" + "github.com/kubewharf/katalyst-core/pkg/metrics" +) + +type EnhancedAdvisor struct { + inner domainAdvisor +} + +func (d *EnhancedAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { + domainStats, subGroups := d.combinedDomainStats(domainsMon) + mbPlan, err := d.inner.GetPlan(ctx, domainStats) + if err != nil { + return nil, err + } + splitPlan := d.splitPlan(mbPlan, subGroups, domainsMon) + return splitPlan, nil +} + +func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, map[string][]string) { + domainStats := &monitor.DomainStats{ + Incomings: make(map[int]monitor.DomainMonStat), + Outgoings: make(map[int]monitor.DomainMonStat), + OutgoingGroupSumStat: make(map[string][]monitor.MBInfo), + } + subGroups := make(map[string][]string) + for id, domainMon := range domainsMon.Incomings { + domainStats.Incomings[id], subGroups = preProcessGroupInfo(domainMon) + } + for id, domainMon := range domainsMon.Outgoings { + domainStats.Outgoings[id], subGroups = preProcessGroupInfo(domainMon) + } + domainStats.OutgoingGroupSumStat = preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) + return domainStats, subGroups +} + +func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, subGroups map[string][]string, domainsMon *monitor.DomainStats) *plan.MBPlan { + for groupKey, ccdPlan := range mbPlan.MBGroups { + if !strings.Contains(groupKey, "combined-") { + continue + } + for _, stats := range domainsMon.Incomings { + subGroupMap := make(map[string][]int) + sumMB := 0 + for group, stat := range stats { + for _, subGroup := range subGroups[groupKey] { + maxMB := 0 + for id, mbInfo := range stat { + sumMB += mbInfo.TotalMB + if group == subGroup { + if mbInfo.TotalMB > maxMB { + subGroupMap[group][0] = id + } + subGroupMap[group][1] += mbInfo.TotalMB + } + } + } + } + for _, subGroup := range subGroups[groupKey] { + ccd := subGroupMap[subGroup][0] + mb := subGroupMap[subGroup][1] + mbPlan.MBGroups[subGroup][ccd] = mb / sumMB * ccdPlan[0] + } + } + delete(mbPlan.MBGroups, groupKey) + } + return mbPlan +} + +func NewEnhancedAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, + capPercent int, XDomGroups []string, groupNeverThrottles []string, + groupCapacity map[string]int, +) Advisor { + return NewDomainAdvisor(emitter, domains, + ccdMaxMB, ccdMaxMB, + defaultDomainCapacity, capPercent, + XDomGroups, groupNeverThrottles, + groupCapacity) +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go index cf6d3571b6..e3c25d562f 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go @@ -19,7 +19,6 @@ package advisor import ( "context" "fmt" - "strings" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/sets" @@ -85,8 +84,7 @@ func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainS // for each group, based on incoming targets, decide what the outgoing targets are var groupedDomOutgoingTargets map[string][]int - outgoingGroupSumStat := preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) - groupedDomOutgoingTargets, err = d.deriveOutgoingTargets(ctx, outgoingGroupSumStat, groupedDomIncomingTargets) + groupedDomOutgoingTargets, err = d.deriveOutgoingTargets(ctx, domainsMon.OutgoingGroupSumStat, groupedDomIncomingTargets) if err != nil { return nil, errors.Wrap(err, "failed to get plan") } @@ -98,7 +96,8 @@ func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainS // leverage the current observed outgoing stats (and implicit previous outgoing mb) // to adjust th outgoing mb hopeful to reach the desired target - groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, outgoingGroupSumStat, d.capPercent) + groupedDomOutgoings := domainsMon.OutgoingGroupSumStat + groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, groupedDomOutgoings, d.capPercent) if klog.V(6).Enabled() { general.InfofV(6, "[mbm] [advisor] group-domain outgoing quotas: %s", stringify(groupedDomainOutgoingQuotas)) @@ -235,68 +234,42 @@ func (d *domainAdvisor) distributeToCCDs(_ context.Context, quotas map[string][]int, outgoingStat map[int]monitor.GroupMBStats, ) map[string]map[int]int { result := map[string]map[int]int{} - for group, domQuota := range quotas { + // each domain is treated independently for domID, domTotal := range domQuota { - outgoings, subGroups := preProcessGroupInfo(outgoingStat[domID]) - - // Determine which groups to distribute - var groupsToDistribute []string - if strings.Contains(group, "combined-") { - groupsToDistribute = subGroups[group] - } else { - groupsToDistribute = []string{group} + ccdDistributions := d.domainDistributeGroup(domID, group, domTotal, outgoingStat) + if len(ccdDistributions) == 0 { + continue } - // Distribute for each group - for _, targetGroup := range groupsToDistribute { - ccdDistributions := d.domainDistributeGroup(domID, group, targetGroup, domTotal, outgoingStat, outgoings) - if len(ccdDistributions) == 0 { - continue - } - - // Accumulate results - if _, ok := result[targetGroup]; !ok { - result[targetGroup] = make(map[int]int) - } - for ccd, v := range ccdDistributions { - result[targetGroup][ccd] = v - } + if _, ok := result[group]; !ok { + result[group] = make(map[int]int) + } + for ccd, v := range ccdDistributions { + result[group][ccd] = v } } } - return result } -func (d *domainAdvisor) domainDistributeGroup(domID int, group string, subGroup string, - domTotal int, outgoingStat map[int]monitor.GroupMBStats, outgoings monitor.GroupMBStats, +func (d *domainAdvisor) domainDistributeGroup(domID int, group string, + domTotal int, outgoingStat map[int]monitor.GroupMBStats, ) map[int]int { weights := map[int]int{} - groupStat := outgoingStat[domID][subGroup] - if group != subGroup { - groupStat = outgoings[group] - } - totalMBSum := 0 + groupStat := outgoingStat[domID][group] for ccd, stat := range groupStat { weights[ccd] = stat.TotalMB - totalMBSum += stat.TotalMB } domCCDQuotas := d.ccdDistribute.Distribute(domTotal, weights) result := map[int]int{} for ccd, v := range domCCDQuotas { - if _, ok := outgoingStat[domID][subGroup][ccd]; ok { - if totalMBSum < domTotal && group != subGroup { - result[ccd] = d.ccdDistribute.GetMax() - continue - } - result[ccd] = v - } + result[ccd] = v } return result } -func New(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, +func NewDomainAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, capPercent int, XDomGroups []string, groupNeverThrottles []string, groupCapacity map[string]int, ) Advisor { diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go index 52d5b12b72..d77159dca0 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go @@ -516,8 +516,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { name: "same priority with not enough capacity for two and a higher priority", fields: fields{ domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), - 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), }, defaultDomainCapacity: 30_000, XDomGroups: nil, @@ -676,8 +676,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { name: "same priority with not enough capacity for two and a lower priority", fields: fields{ domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), - 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), }, defaultDomainCapacity: 30_000, XDomGroups: nil, @@ -836,8 +836,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { name: "same priority with not enough capacity for one and a lower priority", fields: fields{ domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), - 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), }, defaultDomainCapacity: 30_000, XDomGroups: nil, @@ -996,8 +996,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { name: "same priority with partial enough capacity and a lower priority", fields: fields{ domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), - 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), }, defaultDomainCapacity: 30_000, XDomGroups: nil, @@ -1146,8 +1146,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, }, want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 20_000, 3: 20_000}, - "machine-60": {1: 20_000, 4: 20_000}, + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, "share-50": {2: 8500, 5: 8500}, }}, wantErr: false, @@ -1156,8 +1156,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { name: "same priority with fully enough capacity and a lower priority", fields: fields{ domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1), 88888), - 1: domain.NewDomain(1, sets.NewInt(2, 3), 88888), + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), }, defaultDomainCapacity: 30_000, XDomGroups: nil, @@ -1306,8 +1306,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }, }, want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 20_000, 3: 20_000}, - "machine-60": {1: 20_000, 4: 20_000}, + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, "share-50": {2: 10_000, 5: 10_000}, }}, wantErr: false, @@ -1329,7 +1329,8 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { ccdDistribute: distributor.New(0, 20_000), emitter: &metrics.DummyMetrics{}, } - got, err := d.GetPlan(tt.args.ctx, tt.args.domainsMon) + advisor := &EnhancedAdvisor{inner: *d} + got, err := advisor.GetPlan(tt.args.ctx, tt.args.domainsMon) if (err != nil) != tt.wantErr { t.Errorf("GetPlan() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/pkg/agent/qrm-plugins/mb/policy/plugin.go b/pkg/agent/qrm-plugins/mb/policy/plugin.go index cba372d627..a115befd57 100644 --- a/pkg/agent/qrm-plugins/mb/policy/plugin.go +++ b/pkg/agent/qrm-plugins/mb/policy/plugin.go @@ -120,7 +120,7 @@ func (m *MBPlugin) Start() (err error) { } // initializing advisor field is deferred as qos group mb capacities is known now - m.advisor = advisor.New(m.emitter, m.domains, + m.advisor = advisor.NewEnhancedAdvisor(m.emitter, m.domains, m.conf.MinCCDMB, m.conf.MaxCCDMB, defaultMBDomainCapacity, m.conf.MBCapLimitPercent, m.conf.CrossDomainGroups, m.conf.MBQRMPluginConfig.NoThrottleGroups, From 9d140af936f5a1a3faf0a42550395d17364e3e19 Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Tue, 3 Feb 2026 11:44:52 -0800 Subject: [PATCH 04/10] refactor advisor --- pkg/agent/qrm-plugins/mb/advisor/advisor.go | 41 +- .../qrm-plugins/mb/advisor/advisor_helper.go | 12 +- .../qrm-plugins/mb/advisor/advisor_test.go | 869 ++++++++++++++++++ .../mb/advisor/distributor/types.go | 9 - .../mb/advisor/domain_advisor_test.go | 805 +--------------- .../qrm-plugins/mb/advisor/resource/types.go | 1 - 6 files changed, 890 insertions(+), 847 deletions(-) create mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor_test.go diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor.go b/pkg/agent/qrm-plugins/mb/advisor/advisor.go index 1ac4fb46f7..2da7b3a1d0 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor.go @@ -15,59 +15,50 @@ type EnhancedAdvisor struct { } func (d *EnhancedAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { - domainStats, subGroups := d.combinedDomainStats(domainsMon) + domainStats := d.combinedDomainStats(domainsMon) mbPlan, err := d.inner.GetPlan(ctx, domainStats) if err != nil { return nil, err } - splitPlan := d.splitPlan(mbPlan, subGroups, domainsMon) + splitPlan := d.splitPlan(mbPlan, domainsMon) return splitPlan, nil } -func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, map[string][]string) { +func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) *monitor.DomainStats { domainStats := &monitor.DomainStats{ Incomings: make(map[int]monitor.DomainMonStat), Outgoings: make(map[int]monitor.DomainMonStat), OutgoingGroupSumStat: make(map[string][]monitor.MBInfo), } - subGroups := make(map[string][]string) for id, domainMon := range domainsMon.Incomings { - domainStats.Incomings[id], subGroups = preProcessGroupInfo(domainMon) + domainStats.Incomings[id] = preProcessGroupInfo(domainMon) } for id, domainMon := range domainsMon.Outgoings { - domainStats.Outgoings[id], subGroups = preProcessGroupInfo(domainMon) + domainStats.Outgoings[id] = preProcessGroupInfo(domainMon) } domainStats.OutgoingGroupSumStat = preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) - return domainStats, subGroups + return domainStats } -func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, subGroups map[string][]string, domainsMon *monitor.DomainStats) *plan.MBPlan { +func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, domainsMon *monitor.DomainStats) *plan.MBPlan { for groupKey, ccdPlan := range mbPlan.MBGroups { if !strings.Contains(groupKey, "combined-") { continue } - for _, stats := range domainsMon.Incomings { - subGroupMap := make(map[string][]int) - sumMB := 0 - for group, stat := range stats { - for _, subGroup := range subGroups[groupKey] { - maxMB := 0 - for id, mbInfo := range stat { - sumMB += mbInfo.TotalMB - if group == subGroup { - if mbInfo.TotalMB > maxMB { - subGroupMap[group][0] = id + for ccd, quota := range ccdPlan { + for _, stats := range domainsMon.Incomings { + for group, stat := range stats { + for id := range stat { + if id == ccd { + if mbPlan.MBGroups[group] == nil { + mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) } - subGroupMap[group][1] += mbInfo.TotalMB + mbPlan.MBGroups[group][ccd] = quota + break } } } } - for _, subGroup := range subGroups[groupKey] { - ccd := subGroupMap[subGroup][0] - mb := subGroupMap[subGroup][1] - mbPlan.MBGroups[subGroup][ccd] = mb / sumMB * ccdPlan[0] - } } delete(mbPlan.MBGroups, groupKey) } diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index dfb61336d8..a07f3038b4 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -126,12 +126,10 @@ func getGroupIncomingInfo(capacity int, incomingStats monitor.GroupMBStats) *res CapacityInMB: capacity, } - groups, subGroups := preProcessGroupInfo(incomingStats) - result.GroupSorted = sortGroups(maps.Keys(groups)) - result.GroupTotalUses = getUsedTotalByGroup(groups) + result.GroupSorted = sortGroups(maps.Keys(incomingStats)) + result.GroupTotalUses = getUsedTotalByGroup(incomingStats) result.FreeInMB, result.GroupLimits = getLimitsByGroupSorted(capacity, result.GroupSorted, result.GroupTotalUses) result.ResourceState = resource.GetResourceState(capacity, result.FreeInMB) - result.SubGroups = subGroups return result } @@ -146,11 +144,10 @@ func groupByWeight[T any](stats map[string]T) map[int][]string { } // preProcessGroupInfo combines groups with same priority together -func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, map[string][]string) { +func preProcessGroupInfo(stats monitor.GroupMBStats) monitor.GroupMBStats { groups := groupByWeight(stats) result := make(monitor.GroupMBStats) - subGroupsMap := make(map[string][]string) for weight, equivGroups := range groups { if len(equivGroups) == 1 { @@ -159,7 +156,6 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, map[ } newKey := fmt.Sprintf("combined-%d", weight) - subGroupsMap[newKey] = equivGroups combined := make(monitor.GroupMB) for _, group := range equivGroups { @@ -170,7 +166,7 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, map[ result[newKey] = combined } - return result, subGroupsMap + return result } func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]monitor.MBInfo { diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go new file mode 100644 index 0000000000..3c213c9346 --- /dev/null +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go @@ -0,0 +1,869 @@ +package advisor + +import ( + "context" + "reflect" + "testing" + + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/adjuster" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/distributor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/quota" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/sankey" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" + "github.com/kubewharf/katalyst-core/pkg/metrics" + "k8s.io/apimachinery/pkg/util/sets" +) + +func Test_EnhancedAdvisor_GetPlan(t *testing.T) { + t.Parallel() + type fields struct { + domains domain.Domains + defaultDomainCapacity int + XDomGroups sets.String + GroupCapacityInMB map[string]int + quotaStrategy quota.Decider + flower sankey.DomainFlower + adjusters map[string]adjuster.Adjuster + } + type args struct { + ctx context.Context + domainsMon *monitor.DomainStats + } + tests := []struct { + name string + fields fields + args args + want *plan.MBPlan + wantErr bool + }{ + { + name: "same priority with not enough capacity for two and a higher priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "/-100": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 4250, 3: 4250}, + "machine-60": {1: 4250, 4: 4250}, + "/-100": {2: 20_000, 5: 20_000}, + }}, + wantErr: false, + }, + { + name: "same priority with not enough capacity for two and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": { + 0: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 14_250, 3: 14_250}, + "machine-60": {1: 14_250, 4: 14_250}, + "share-50": {2: 0, 5: 0}, + }}, + wantErr: false, + }, + { + name: "same priority with not enough capacity for one and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 10_000, + RemoteMB: 10_000, + TotalMB: 20_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 20_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + 1: { + LocalMB: 20_000, + RemoteMB: 20_000, + TotalMB: 40_000, + }, + }, + "share-50": { + 0: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 0, + TotalMB: 10_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 14_250, 3: 14_250}, + "machine-60": {1: 14_250, 4: 14_250}, + "share-50": {2: 0, 5: 0}, + }}, + wantErr: false, + }, + { + name: "same priority with partial enough capacity and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": { + 0: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + 1: { + LocalMB: 10_000, + RemoteMB: 5_000, + TotalMB: 15_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, + "share-50": {2: 8500, 5: 8500}, + }}, + wantErr: false, + }, + { + name: "same priority with fully enough capacity and a lower priority", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": { + 0: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, + "share-50": {2: 10_000, 5: 10_000}, + }}, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &domainAdvisor{ + domains: tt.fields.domains, + defaultDomainCapacity: tt.fields.defaultDomainCapacity, + capPercent: 100, + xDomGroups: tt.fields.XDomGroups, + groupCapacityInMB: tt.fields.GroupCapacityInMB, + quotaStrategy: tt.fields.quotaStrategy, + flower: tt.fields.flower, + adjusters: tt.fields.adjusters, + ccdDistribute: distributor.New(0, 20_000), + emitter: &metrics.DummyMetrics{}, + } + advisor := &EnhancedAdvisor{inner: *d} + got, err := advisor.GetPlan(tt.args.ctx, tt.args.domainsMon) + if (err != nil) != tt.wantErr { + t.Errorf("GetPlan() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPlan() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go index 406f70fa2d..56ace05b0b 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go +++ b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go @@ -21,7 +21,6 @@ import "math" type Distributor interface { // Distribute distributes total mb into ccds by their relative weights Distribute(total int, weights map[int]int) map[int]int - GetMax() int } func New(min, max int) Distributor { @@ -66,10 +65,6 @@ func (l *linearBoundedDistributor) adjust(value int) int { return value } -func (l *linearBoundedDistributor) GetMax() int { - return l.max -} - func getPortion(total int, weight int, totalWeight int) int { if weight <= 0 || totalWeight <= 0 { return 0 @@ -93,7 +88,3 @@ func (l logarithmicBoundedDistributor) Distribute(total int, weights map[int]int } return l.inner.Distribute(total, logarithmicWeights) } - -func (l logarithmicBoundedDistributor) GetMax() int { - return l.inner.max -} diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go index d77159dca0..5c3ba41968 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go @@ -170,7 +170,6 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { "share-50": 10_000 - 2_200, }, ResourceState: resource.State("fit"), - SubGroups: map[string][]string{}, }, }, wantErr: false, @@ -218,7 +217,6 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { "share-50": 6_000 - 2_200, }, ResourceState: resource.State("underStress"), - SubGroups: map[string][]string{}, }, }, wantErr: false, @@ -512,806 +510,6 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { }}, wantErr: false, }, - { - name: "same priority with not enough capacity for two and a higher priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 4250, 3: 4250}, - "machine-60": {1: 4250, 4: 4250}, - "/-100": {2: 20_000, 5: 20_000}, - }}, - wantErr: false, - }, - { - name: "same priority with not enough capacity for two and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 14_250, 3: 14_250}, - "machine-60": {1: 14_250, 4: 14_250}, - "share-50": {2: 0, 5: 0}, - }}, - wantErr: false, - }, - { - name: "same priority with not enough capacity for one and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 14_250, 3: 14_250}, - "machine-60": {1: 14_250, 4: 14_250}, - "share-50": {2: 0, 5: 0}, - }}, - wantErr: false, - }, - { - name: "same priority with partial enough capacity and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, - "share-50": {2: 8500, 5: 8500}, - }}, - wantErr: false, - }, - { - name: "same priority with fully enough capacity and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": { - 0: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, - "share-50": {2: 10_000, 5: 10_000}, - }}, - wantErr: false, - }, } for _, tt := range tests { tt := tt @@ -1329,8 +527,7 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { ccdDistribute: distributor.New(0, 20_000), emitter: &metrics.DummyMetrics{}, } - advisor := &EnhancedAdvisor{inner: *d} - got, err := advisor.GetPlan(tt.args.ctx, tt.args.domainsMon) + got, err := d.GetPlan(tt.args.ctx, tt.args.domainsMon) if (err != nil) != tt.wantErr { t.Errorf("GetPlan() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/pkg/agent/qrm-plugins/mb/advisor/resource/types.go b/pkg/agent/qrm-plugins/mb/advisor/resource/types.go index bd210cc60d..84166f086f 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/resource/types.go +++ b/pkg/agent/qrm-plugins/mb/advisor/resource/types.go @@ -55,5 +55,4 @@ type MBGroupIncomingStat struct { ResourceState State GroupLimits GroupSettings GroupSorted []sets.String - SubGroups map[string][]string } From ee97bd051426947a3534036a64d131b81c8427b4 Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Tue, 3 Feb 2026 16:16:17 -0800 Subject: [PATCH 05/10] add more tests --- pkg/agent/qrm-plugins/mb/advisor/advisor.go | 25 +- .../qrm-plugins/mb/advisor/advisor_helper.go | 4 +- .../qrm-plugins/mb/advisor/advisor_test.go | 396 ++++++++++++++++++ 3 files changed, 419 insertions(+), 6 deletions(-) diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor.go b/pkg/agent/qrm-plugins/mb/advisor/advisor.go index 2da7b3a1d0..3b27527705 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor.go @@ -2,6 +2,7 @@ package advisor import ( "context" + "errors" "strings" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" @@ -20,8 +21,7 @@ func (d *EnhancedAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.Domai if err != nil { return nil, err } - splitPlan := d.splitPlan(mbPlan, domainsMon) - return splitPlan, nil + return d.splitPlan(mbPlan, domainsMon) } func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) *monitor.DomainStats { @@ -40,11 +40,12 @@ func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) * return domainStats } -func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, domainsMon *monitor.DomainStats) *plan.MBPlan { +func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { for groupKey, ccdPlan := range mbPlan.MBGroups { if !strings.Contains(groupKey, "combined-") { continue } + maxMap := make(map[int]int) for ccd, quota := range ccdPlan { for _, stats := range domainsMon.Incomings { for group, stat := range stats { @@ -54,15 +55,29 @@ func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, domainsMon *monitor.Dom mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) } mbPlan.MBGroups[group][ccd] = quota - break + } + if stat[id].TotalMB > maxMap[id] { + maxMap[id] = stat[id].TotalMB } } } } } delete(mbPlan.MBGroups, groupKey) + for _, stats := range domainsMon.Incomings { + for group, stat := range stats { + for id, mbStat := range stat { + if mbStat.TotalMB > maxMap[id]/2 && mbStat.TotalMB < maxMap[id] { + return nil, errors.New("invalid incoming inputs") + } + if mbStat.TotalMB <= maxMap[id]/2 { + delete(mbPlan.MBGroups[group], id) + } + } + } + } } - return mbPlan + return mbPlan, nil } func NewEnhancedAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index a07f3038b4..6f31c976a7 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -160,7 +160,9 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) monitor.GroupMBStats { combined := make(monitor.GroupMB) for _, group := range equivGroups { for id, stat := range stats[group] { - combined[id] = stat + if stat.TotalMB > combined[id].TotalMB { + combined[id] = stat + } } } result[newKey] = combined diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go index 3c213c9346..1ffce820fc 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go @@ -838,6 +838,402 @@ func Test_EnhancedAdvisor_GetPlan(t *testing.T) { }}, wantErr: false, }, + { + name: "same priority with shared ccd", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 4: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 4: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 500, + RemoteMB: 500, + TotalMB: 1000, + }, + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 5_500, + RemoteMB: 5_500, + TotalMB: 11_000, + }, + 1: { + LocalMB: 5_500, + RemoteMB: 5_500, + TotalMB: 11_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 5_500, + RemoteMB: 5_500, + TotalMB: 11_000, + }, + 1: { + LocalMB: 5_500, + RemoteMB: 5_500, + TotalMB: 11_000, + }, + }, + "share-50": { + 0: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + }, + want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 15_000, 3: 15_000}, + "machine-60": {1: 15_000, 4: 15_000}, + "share-50": {2: 10_000, 5: 10_000}, + }}, + wantErr: false, + }, + { + name: "invalid incomings with shared ccd", + fields: fields{ + domains: domain.Domains{ + 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), + 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), + }, + defaultDomainCapacity: 30_000, + XDomGroups: nil, + GroupCapacityInMB: nil, + quotaStrategy: quota.New(), + flower: sankey.New(), + adjusters: map[string]adjuster.Adjuster{}, + }, + args: args{ + ctx: context.TODO(), + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 4: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 1: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 0: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 2: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + 4: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: { + LocalMB: 4_000, + RemoteMB: 5_000, + TotalMB: 9_000, + }, + 4: { + LocalMB: 5_000, + RemoteMB: 5_000, + TotalMB: 10_000, + }, + }, + "share-50": map[int]monitor.MBInfo{ + 5: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + 0: { + LocalMB: 9_000, + RemoteMB: 10_000, + TotalMB: 19_000, + }, + 1: { + LocalMB: 9_000, + RemoteMB: 10_000, + TotalMB: 19_000, + }, + }, + "machine-60": { + 0: { + LocalMB: 9_000, + RemoteMB: 10_000, + TotalMB: 19_000, + }, + 1: { + LocalMB: 9_000, + RemoteMB: 10_000, + TotalMB: 19_000, + }, + }, + "share-50": { + 0: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + 1: { + LocalMB: 5_000, + RemoteMB: 0, + TotalMB: 5_000, + }, + }, + }, + }, + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { tt := tt From 072b2c8bafde45365e49c9d68dbd04bc241e44bf Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Wed, 4 Feb 2026 16:34:22 -0800 Subject: [PATCH 06/10] refactor code --- pkg/agent/qrm-plugins/mb/advisor/advisor.go | 62 +- .../qrm-plugins/mb/advisor/advisor_helper.go | 29 +- .../mb/advisor/advisor_helper_test.go | 305 +++++++++ .../qrm-plugins/mb/advisor/advisor_test.go | 584 ++++++++++++++++++ 4 files changed, 943 insertions(+), 37 deletions(-) diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor.go b/pkg/agent/qrm-plugins/mb/advisor/advisor.go index 3b27527705..af5b3205b3 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor.go @@ -2,7 +2,6 @@ package advisor import ( "context" - "errors" "strings" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" @@ -16,68 +15,63 @@ type EnhancedAdvisor struct { } func (d *EnhancedAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { - domainStats := d.combinedDomainStats(domainsMon) + domainStats, groupInfos, err := d.combinedDomainStats(domainsMon) + if err != nil { + return nil, err + } mbPlan, err := d.inner.GetPlan(ctx, domainStats) if err != nil { return nil, err } - return d.splitPlan(mbPlan, domainsMon) + return d.splitPlan(mbPlan, groupInfos), nil } -func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) *monitor.DomainStats { +func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, *monitor.GroupInfo, error) { domainStats := &monitor.DomainStats{ Incomings: make(map[int]monitor.DomainMonStat), Outgoings: make(map[int]monitor.DomainMonStat), OutgoingGroupSumStat: make(map[string][]monitor.MBInfo), } + groupInfos := &monitor.GroupInfo{ + DomainGroups: make(map[int]monitor.DomainGroupMapping), + } + var err error for id, domainMon := range domainsMon.Incomings { - domainStats.Incomings[id] = preProcessGroupInfo(domainMon) + domainStats.Incomings[id], groupInfos.DomainGroups[id], err = preProcessGroupInfo(domainMon) + if err != nil { + return nil, nil, err + } } for id, domainMon := range domainsMon.Outgoings { - domainStats.Outgoings[id] = preProcessGroupInfo(domainMon) + domainStats.Outgoings[id], _, err = preProcessGroupInfo(domainMon) + if err != nil { + return nil, nil, err + } } domainStats.OutgoingGroupSumStat = preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) - return domainStats + return domainStats, groupInfos, nil } -func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { +func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, groupInfos *monitor.GroupInfo) *plan.MBPlan { for groupKey, ccdPlan := range mbPlan.MBGroups { if !strings.Contains(groupKey, "combined-") { continue } - maxMap := make(map[int]int) - for ccd, quota := range ccdPlan { - for _, stats := range domainsMon.Incomings { - for group, stat := range stats { - for id := range stat { - if id == ccd { - if mbPlan.MBGroups[group] == nil { - mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) - } - mbPlan.MBGroups[group][ccd] = quota - } - if stat[id].TotalMB > maxMap[id] { - maxMap[id] = stat[id].TotalMB + for _, domainGroupInfos := range groupInfos.DomainGroups { + for group, groupInfo := range domainGroupInfos[groupKey] { + for ccd := range groupInfo { + if _, exists := ccdPlan[ccd]; exists { + if mbPlan.MBGroups[group] == nil { + mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) } + mbPlan.MBGroups[group][ccd] = ccdPlan[ccd] } } } } delete(mbPlan.MBGroups, groupKey) - for _, stats := range domainsMon.Incomings { - for group, stat := range stats { - for id, mbStat := range stat { - if mbStat.TotalMB > maxMap[id]/2 && mbStat.TotalMB < maxMap[id] { - return nil, errors.New("invalid incoming inputs") - } - if mbStat.TotalMB <= maxMap[id]/2 { - delete(mbPlan.MBGroups[group], id) - } - } - } - } } - return mbPlan, nil + return mbPlan } func NewEnhancedAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index 6f31c976a7..5c9d60bb2e 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -17,6 +17,7 @@ limitations under the License. package advisor import ( + "errors" "fmt" "strings" @@ -144,10 +145,11 @@ func groupByWeight[T any](stats map[string]T) map[int][]string { } // preProcessGroupInfo combines groups with same priority together -func preProcessGroupInfo(stats monitor.GroupMBStats) monitor.GroupMBStats { +func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, monitor.DomainGroupMapping, error) { groups := groupByWeight(stats) result := make(monitor.GroupMBStats) + groupInfos := monitor.DomainGroupMapping{} for weight, equivGroups := range groups { if len(equivGroups) == 1 { @@ -156,19 +158,40 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) monitor.GroupMBStats { } newKey := fmt.Sprintf("combined-%d", weight) - + groupInfo := monitor.CombinedGroupMapping{} combined := make(monitor.GroupMB) + maxMap := make(map[int]int) + + // First pass: find max TotalMB for each CCD and build combined stats for _, group := range equivGroups { for id, stat := range stats[group] { if stat.TotalMB > combined[id].TotalMB { combined[id] = stat + maxMap[id] = stat.TotalMB + } + } + } + + // Second pass: validate and build CCD sets for each group (only within equivGroups) + for _, group := range equivGroups { + ccdSet := monitor.CCDSet{} + for id, mbStat := range stats[group] { + // skip shared ccd with similar incoming data + if mbStat.TotalMB > maxMap[id]/2 && mbStat.TotalMB < maxMap[id] { + return nil, nil, errors.New("invalid incoming inputs") + } + if mbStat.TotalMB == maxMap[id] { + ccdSet[id] = struct{}{} } } + groupInfo[group] = ccdSet } + result[newKey] = combined + groupInfos[newKey] = groupInfo } - return result + return result, groupInfos, nil } func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]monitor.MBInfo { diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go index 948ad4dcae..cdb33b42b5 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/resource" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" ) @@ -179,3 +180,307 @@ func Test_getDomainTotalMBs(t *testing.T) { }) } } + +func Test_preProcessGroupInfo(t *testing.T) { + t.Parallel() + tests := []struct { + name string + stats monitor.GroupMBStats + wantResult monitor.GroupMBStats + wantGroupInfos monitor.DomainGroupMapping + wantErr bool + }{ + { + name: "empty stats", + stats: monitor.GroupMBStats{}, + wantResult: monitor.GroupMBStats{}, + wantGroupInfos: monitor.DomainGroupMapping{}, + wantErr: false, + }, + { + name: "single group - no combination needed", + stats: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + wantResult: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + wantGroupInfos: monitor.DomainGroupMapping{}, + wantErr: false, + }, + { + name: "two groups with different weights - no combination", + stats: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + }, + "share-50": { + 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + wantResult: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + }, + "share-50": { + 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + wantGroupInfos: monitor.DomainGroupMapping{}, + wantErr: false, + }, + { + name: "two groups with same weight - combine into one", + stats: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": { + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + wantResult: monitor.GroupMBStats{ + "combined-9000": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + wantGroupInfos: monitor.DomainGroupMapping{ + "combined-9000": { + "dedicated": {0: struct{}{}}, + "machine": {1: struct{}{}}, + }, + }, + wantErr: false, + }, + { + name: "three groups with same weight - combine into one", + stats: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": { + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "system": { + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + wantResult: monitor.GroupMBStats{ + "combined-9000": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + wantGroupInfos: monitor.DomainGroupMapping{ + "combined-9000": { + "dedicated": {0: struct{}{}}, + "machine": {1: struct{}{}}, + "system": {2: struct{}{}}, + }, + }, + wantErr: false, + }, + { + name: "mixed groups - some combined some not", + stats: monitor.GroupMBStats{ + "dedicated": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": { + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "share-50": { + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + wantResult: monitor.GroupMBStats{ + "combined-9000": { + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "share-50": { + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + wantGroupInfos: monitor.DomainGroupMapping{ + "combined-9000": { + "dedicated": {0: struct{}{}}, + "machine": {1: struct{}{}}, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + gotResult, gotGroupInfos, err := preProcessGroupInfo(tt.stats) + if (err != nil) != tt.wantErr { + t.Errorf("preProcessGroupInfo() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotResult, tt.wantResult) { + t.Errorf("preProcessGroupInfo() gotResult = %v, want %v", gotResult, tt.wantResult) + } + if !reflect.DeepEqual(gotGroupInfos, tt.wantGroupInfos) { + t.Errorf("preProcessGroupInfo() gotGroupInfos = %v, want %v", gotGroupInfos, tt.wantGroupInfos) + } + }) + } +} + +func Test_preProcessGroupSumStat(t *testing.T) { + t.Parallel() + tests := []struct { + name string + sumStats map[string][]monitor.MBInfo + want map[string][]monitor.MBInfo + }{ + { + name: "empty stats", + sumStats: map[string][]monitor.MBInfo{}, + want: map[string][]monitor.MBInfo{}, + }, + { + name: "single group - no combination needed", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + want: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + }, + }, + { + name: "two groups with different weights - no combination", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + "share-50": { + {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + }, + }, + want: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + "share-50": { + {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + }, + }, + }, + { + name: "two groups with same weight - combine and sum", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + "machine": { + {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + }, + }, + want: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + { + name: "three groups with same weight - combine and sum all", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + "machine": { + {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + }, + "system": { + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, + }, + }, + want: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + {LocalMB: 7_000, RemoteMB: 3_500, TotalMB: 10_500}, + }, + }, + }, + { + name: "mixed groups - some combined some not", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, + {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, + }, + "machine": { + {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, + {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, + }, + "share-50": { + {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, + {LocalMB: 800, RemoteMB: 400, TotalMB: 1_200}, + }, + }, + want: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + "share-50": { + {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, + {LocalMB: 800, RemoteMB: 400, TotalMB: 1_200}, + }, + }, + }, + { + name: "single domain stats", + sumStats: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + want: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, + }, + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if got := preProcessGroupSumStat(tt.sumStats); !reflect.DeepEqual(got, tt.want) { + t.Errorf("preProcessGroupSumStat() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go index 1ffce820fc..411a0ddf28 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go @@ -1263,3 +1263,587 @@ func Test_EnhancedAdvisor_GetPlan(t *testing.T) { }) } } + +func Test_EnhancedAdvisor_combinedDomainStats(t *testing.T) { + t.Parallel() + tests := []struct { + name string + domainsMon *monitor.DomainStats + wantStats *monitor.DomainStats + wantGroupInfo *monitor.GroupInfo + wantErr bool + }{ + { + name: "single group per weight - no combination", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + }, + "share-50": { + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + }, + "share-50": { + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantGroupInfo: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: {}, + 1: {}, + }, + }, + wantErr: false, + }, + { + name: "multiple groups with same weight - combine groups", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, + }, + }, + }, + wantGroupInfo: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "multiple domains with same weight groups", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + 1: { + "dedicated-60": map[int]monitor.MBInfo{ + 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, + }, + "machine-60": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + 1: { + "combined-9000": map[int]monitor.MBInfo{ + 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, + 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + 1: { + "combined-9000": map[int]monitor.MBInfo{ + 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, + 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, + {LocalMB: 19_000, RemoteMB: 9_000, TotalMB: 28_000}, + }, + }, + }, + wantGroupInfo: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + 1: { + "combined-9000": { + "dedicated-60": {2: struct{}{}}, + "machine-60": {3: struct{}{}}, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "three groups with same weight", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "system-60": map[int]monitor.MBInfo{ + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "system-60": map[int]monitor.MBInfo{ + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine-60": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + "system-60": { + {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 24_000, RemoteMB: 12_000, TotalMB: 36_000}, + }, + }, + }, + wantGroupInfo: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + "system-60": {2: struct{}{}}, + }, + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &EnhancedAdvisor{} + gotStats, gotGroupInfo, err := d.combinedDomainStats(tt.domainsMon) + if (err != nil) != tt.wantErr { + t.Errorf("combinedDomainStats() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotStats, tt.wantStats) { + t.Errorf("combinedDomainStats() gotStats = %v, want %v", gotStats, tt.wantStats) + } + if !reflect.DeepEqual(gotGroupInfo, tt.wantGroupInfo) { + t.Errorf("combinedDomainStats() gotGroupInfo = %v, want %v", gotGroupInfo, tt.wantGroupInfo) + } + }) + } +} + +func Test_EnhancedAdvisor_splitPlan(t *testing.T) { + t.Parallel() + tests := []struct { + name string + mbPlan *plan.MBPlan + groupInfos *monitor.GroupInfo + want *plan.MBPlan + }{ + { + name: "no combined groups - no change", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000, 1: 4_000}, + "machine-60": {2: 6_000, 3: 5_500}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: {}, + 1: {}, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000, 1: 4_000}, + "machine-60": {2: 6_000, 3: 5_500}, + }, + }, + }, + { + name: "single combined group - split to original groups", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + }, + }, + }, + { + name: "mixed combined and non-combined groups", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000}, + "share-50": {2: 8_000, 3: 7_000}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + "share-50": {2: 8_000, 3: 7_000}, + }, + }, + }, + { + name: "multiple combined groups in different domains", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000, 2: 6_000, 3: 5_500}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + 1: { + "combined-9000": { + "dedicated-60": {2: struct{}{}}, + "machine-60": {3: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000, 2: 6_000}, + "machine-60": {1: 4_000, 3: 5_500}, + }, + }, + }, + { + name: "combined group with partial CCD match", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000, 2: 3_000}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + }, + }, + }, + { + name: "multiple combined groups with different priorities", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000}, + "combined-1050": {2: 8_000, 3: 7_000}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + "combined-1050": { + "share-50": {2: struct{}{}}, + "share-alt-50": {3: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + "share-50": {2: 8_000}, + "share-alt-50": {3: 7_000}, + }, + }, + }, + { + name: "empty group info - remove combined groups", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{}, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{}, + }, + }, + { + name: "three groups combined and split", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000, 2: 3_500}, + }, + }, + groupInfos: &monitor.GroupInfo{ + DomainGroups: map[int]monitor.DomainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + "system-60": {2: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + "system-60": {2: 3_500}, + }, + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &EnhancedAdvisor{} + got := d.splitPlan(tt.mbPlan, tt.groupInfos) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("splitPlan() = %v, want %v", got, tt.want) + } + }) + } +} From 658818b726838fae49d5b1cd798a00c4fc3c5d9b Mon Sep 17 00:00:00 2001 From: "daocheng.xu" Date: Mon, 9 Feb 2026 11:20:37 -0800 Subject: [PATCH 07/10] add missing file --- pkg/agent/qrm-plugins/mb/monitor/domain_stat.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go b/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go index 8f3c039bdb..525ae61db4 100644 --- a/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go +++ b/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go @@ -40,6 +40,20 @@ type DomainStats struct { // DomainMonStat is memory bandwidth statistic info of one domain, each has multiple groups type DomainMonStat = GroupMBStats +// GroupInfo stores the mapping of groups and their CCDs for each domain +type GroupInfo struct { // DomainGroups maps domain ID -> combined group key -> original group key -> CCD IDs + DomainGroups map[int]DomainGroupMapping +} + +// DomainGroupMapping maps combined group keys to their original groups +type DomainGroupMapping map[string]CombinedGroupMapping + +// CombinedGroupMapping maps original group keys to their CCD IDs +type CombinedGroupMapping map[string]CCDSet + +// CCDSet represents a set of CCD IDs +type CCDSet map[int]struct{} + // NewDomainStats splits group-style outgoing mb stat (as from resctrl mon-data) into corresponding domains, // and attributes incoming traffic from outgoings for the cross-domain groups func NewDomainStats(statOutgoing GroupMBStats, ccdToDomain map[int]int, xDomGroups sets.String) (*DomainStats, error) { From 5b51e32936d907e48fb08018387c4b1e64ec1837 Mon Sep 17 00:00:00 2001 From: Hongwei Chen Date: Tue, 10 Feb 2026 19:22:46 +0000 Subject: [PATCH 08/10] args --mb-extra-group-priorities=machine=9000 --mb-group-priority-unique=false; simplify test cases --- .../app/options/qrm/mb_plugin.go | 8 + pkg/agent/qrm-plugins/mb/advisor/advisor.go | 86 - .../mb/advisor/advisor_decorator.go | 114 + .../mb/advisor/advisor_decorator_test.go | 277 +++ .../qrm-plugins/mb/advisor/advisor_helper.go | 13 +- .../mb/advisor/advisor_helper_test.go | 180 +- .../qrm-plugins/mb/advisor/advisor_test.go | 1849 ----------------- .../mb/advisor/distributor/types.go | 7 +- .../qrm-plugins/mb/advisor/domain_advisor.go | 15 +- .../mb/advisor/domain_advisor_test.go | 2 +- .../mb/advisor/priority/group_priority.go | 101 + .../mb/advisor/{ => priority}/group_sort.go | 63 +- .../advisor/{ => priority}/group_sort_test.go | 4 +- .../qrm-plugins/mb/monitor/domain_stat.go | 14 - pkg/agent/qrm-plugins/mb/policy/plugin.go | 17 +- pkg/config/agent/qrm/mb_plugin.go | 2 + pkg/consts/resctrl.go | 1 - 17 files changed, 556 insertions(+), 2197 deletions(-) delete mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor.go create mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go create mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go delete mode 100644 pkg/agent/qrm-plugins/mb/advisor/advisor_test.go create mode 100644 pkg/agent/qrm-plugins/mb/advisor/priority/group_priority.go rename pkg/agent/qrm-plugins/mb/advisor/{ => priority}/group_sort.go (51%) rename pkg/agent/qrm-plugins/mb/advisor/{ => priority}/group_sort_test.go (93%) diff --git a/cmd/katalyst-agent/app/options/qrm/mb_plugin.go b/cmd/katalyst-agent/app/options/qrm/mb_plugin.go index 4f0501bb7f..ec00e05fac 100644 --- a/cmd/katalyst-agent/app/options/qrm/mb_plugin.go +++ b/cmd/katalyst-agent/app/options/qrm/mb_plugin.go @@ -52,6 +52,8 @@ type MBOptions struct { CrossDomainGroups []string ResetResctrlOnly bool LocalIsVictimAndTotalIsAllRead bool + GroupPriorityUnique bool + ExtraGroupPriorities map[string]int } func NewMBOptions() *MBOptions { @@ -89,6 +91,10 @@ func (o *MBOptions) AddFlags(fss *cliflag.NamedFlagSets) { o.ResetResctrlOnly, "not to run mb plugin really, and only reset to ensure resctrl FS in default status") fs.BoolVar(&o.LocalIsVictimAndTotalIsAllRead, "mb-local-is-victim", o.LocalIsVictimAndTotalIsAllRead, "turn resctrl local as victim") + fs.BoolVar(&o.GroupPriorityUnique, "mb-group-priority-unique", + o.GroupPriorityUnique, "use equality groups enhanced mb advisor") + fs.StringToIntVar(&o.ExtraGroupPriorities, "mb-extra-group-priorities", + o.ExtraGroupPriorities, "extra resctrl groups with priorities") } func (o *MBOptions) ApplyTo(conf *qrm.MBQRMPluginConfig) error { @@ -103,5 +109,7 @@ func (o *MBOptions) ApplyTo(conf *qrm.MBQRMPluginConfig) error { conf.DomainGroupAwareCapacityPCT = o.DomainGroupAwareCapacityPCT conf.ResetResctrlOnly = o.ResetResctrlOnly conf.LocalIsVictimAndTotalIsAllRead = o.LocalIsVictimAndTotalIsAllRead + conf.GroupPriorityUnique = o.GroupPriorityUnique + conf.ExtraGroupPriorities = o.ExtraGroupPriorities return nil } diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor.go b/pkg/agent/qrm-plugins/mb/advisor/advisor.go deleted file mode 100644 index af5b3205b3..0000000000 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor.go +++ /dev/null @@ -1,86 +0,0 @@ -package advisor - -import ( - "context" - "strings" - - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" - "github.com/kubewharf/katalyst-core/pkg/metrics" -) - -type EnhancedAdvisor struct { - inner domainAdvisor -} - -func (d *EnhancedAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { - domainStats, groupInfos, err := d.combinedDomainStats(domainsMon) - if err != nil { - return nil, err - } - mbPlan, err := d.inner.GetPlan(ctx, domainStats) - if err != nil { - return nil, err - } - return d.splitPlan(mbPlan, groupInfos), nil -} - -func (d *EnhancedAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, *monitor.GroupInfo, error) { - domainStats := &monitor.DomainStats{ - Incomings: make(map[int]monitor.DomainMonStat), - Outgoings: make(map[int]monitor.DomainMonStat), - OutgoingGroupSumStat: make(map[string][]monitor.MBInfo), - } - groupInfos := &monitor.GroupInfo{ - DomainGroups: make(map[int]monitor.DomainGroupMapping), - } - var err error - for id, domainMon := range domainsMon.Incomings { - domainStats.Incomings[id], groupInfos.DomainGroups[id], err = preProcessGroupInfo(domainMon) - if err != nil { - return nil, nil, err - } - } - for id, domainMon := range domainsMon.Outgoings { - domainStats.Outgoings[id], _, err = preProcessGroupInfo(domainMon) - if err != nil { - return nil, nil, err - } - } - domainStats.OutgoingGroupSumStat = preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) - return domainStats, groupInfos, nil -} - -func (d *EnhancedAdvisor) splitPlan(mbPlan *plan.MBPlan, groupInfos *monitor.GroupInfo) *plan.MBPlan { - for groupKey, ccdPlan := range mbPlan.MBGroups { - if !strings.Contains(groupKey, "combined-") { - continue - } - for _, domainGroupInfos := range groupInfos.DomainGroups { - for group, groupInfo := range domainGroupInfos[groupKey] { - for ccd := range groupInfo { - if _, exists := ccdPlan[ccd]; exists { - if mbPlan.MBGroups[group] == nil { - mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) - } - mbPlan.MBGroups[group][ccd] = ccdPlan[ccd] - } - } - } - } - delete(mbPlan.MBGroups, groupKey) - } - return mbPlan -} - -func NewEnhancedAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, - capPercent int, XDomGroups []string, groupNeverThrottles []string, - groupCapacity map[string]int, -) Advisor { - return NewDomainAdvisor(emitter, domains, - ccdMaxMB, ccdMaxMB, - defaultDomainCapacity, capPercent, - XDomGroups, groupNeverThrottles, - groupCapacity) -} diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go new file mode 100644 index 0000000000..56dd53510c --- /dev/null +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go @@ -0,0 +1,114 @@ +/* +Copyright 2022 The Katalyst 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. +*/ + +package advisor + +import ( + "context" + "strings" + + "k8s.io/apimachinery/pkg/util/sets" + + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" +) + +// priorityGroupDecorator adapts with resctrl groups of identical priority as if a logical group. +// It targets the scenarios where the groups of same priority don't share ccd. +// todo: enhance to handle multiple groups of same priority sharing ccd +type priorityGroupDecorator struct { + inner Advisor +} + +// groupInfo stores the mapping of groups and their CCDs for each domain +type groupInfo struct { // DomainGroups maps domain ID -> combined group key -> original group key -> CCD IDs + DomainGroups map[int]domainGroupMapping +} + +// domainGroupMapping maps combined group keys to their original groups +type domainGroupMapping map[string]combinedGroupMapping + +// combinedGroupMapping maps original group keys to their CCD IDs +type combinedGroupMapping map[string]ccdSet + +// ccdSet represents a set of CCD IDs +type ccdSet = sets.Int + +func (d *priorityGroupDecorator) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { + domainStats, groupInfos, err := d.combinedDomainStats(domainsMon) + if err != nil { + return nil, err + } + mbPlan, err := d.inner.GetPlan(ctx, domainStats) + if err != nil { + return nil, err + } + return d.splitPlan(mbPlan, groupInfos), nil +} + +func (d *priorityGroupDecorator) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, *groupInfo, error) { + domainStats := &monitor.DomainStats{ + Incomings: make(map[int]monitor.DomainMonStat), + Outgoings: make(map[int]monitor.DomainMonStat), + OutgoingGroupSumStat: make(map[string][]monitor.MBInfo), + } + groupInfos := &groupInfo{ + DomainGroups: make(map[int]domainGroupMapping), + } + var err error + for id, domainMon := range domainsMon.Incomings { + domainStats.Incomings[id], groupInfos.DomainGroups[id], err = preProcessGroupInfo(domainMon) + if err != nil { + return nil, nil, err + } + } + for id, domainMon := range domainsMon.Outgoings { + domainStats.Outgoings[id], _, err = preProcessGroupInfo(domainMon) + if err != nil { + return nil, nil, err + } + } + domainStats.OutgoingGroupSumStat = preProcessGroupSumStat(domainsMon.OutgoingGroupSumStat) + return domainStats, groupInfos, nil +} + +func (d *priorityGroupDecorator) splitPlan(mbPlan *plan.MBPlan, groupInfos *groupInfo) *plan.MBPlan { + for groupKey, ccdPlan := range mbPlan.MBGroups { + if !strings.Contains(groupKey, "combined-") { + continue + } + for _, domainGroupInfos := range groupInfos.DomainGroups { + for group, groupInfo := range domainGroupInfos[groupKey] { + for ccd := range groupInfo { + if _, exists := ccdPlan[ccd]; exists { + if mbPlan.MBGroups[group] == nil { + mbPlan.MBGroups[group] = make(plan.GroupCCDPlan) + } + mbPlan.MBGroups[group][ccd] = ccdPlan[ccd] + } + } + } + } + delete(mbPlan.MBGroups, groupKey) + } + return mbPlan +} + +func DecorateByPriorityGroup(advisor Advisor) Advisor { + return &priorityGroupDecorator{ + inner: advisor, + } +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go new file mode 100644 index 0000000000..e9a921d476 --- /dev/null +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go @@ -0,0 +1,277 @@ +/* +Copyright 2022 The Katalyst 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. +*/ + +package advisor + +import ( + "reflect" + "testing" + + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/priority" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" +) + +func Test_priorityGroupDecorator_combinedDomainStats(t *testing.T) { + t.Parallel() + priority.GetInstance().AddWeight("machine", 9_000) + tests := []struct { + name string + domainsMon *monitor.DomainStats + wantStats *monitor.DomainStats + wantGroupInfo *groupInfo + wantErr bool + }{ + { + name: "single group per weight - no combination", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + }, + "share-50": { + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated-60": map[int]monitor.MBInfo{ + 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, + }, + }, + 1: { + "share-50": map[int]monitor.MBInfo{ + 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated-60": { + {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + }, + "share-50": { + {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantGroupInfo: &groupInfo{ + DomainGroups: map[int]domainGroupMapping{ + 0: {}, + 1: {}, + }, + }, + wantErr: false, + }, + { + name: "multiple groups with same weight - combine groups", + domainsMon: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "dedicated": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": map[int]monitor.MBInfo{ + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "dedicated": { + {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + }, + "machine": { + {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + wantStats: &monitor.DomainStats{ + Incomings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + Outgoings: map[int]monitor.GroupMBStats{ + 0: { + "combined-9000": map[int]monitor.MBInfo{ + 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, + 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, + }, + }, + }, + OutgoingGroupSumStat: map[string][]monitor.MBInfo{ + "combined-9000": { + {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, + }, + }, + }, + wantGroupInfo: &groupInfo{ + DomainGroups: map[int]domainGroupMapping{ + 0: { + "combined-9000": { + "dedicated": {0: struct{}{}}, + "machine": {1: struct{}{}}, + }, + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &priorityGroupDecorator{} + gotStats, gotGroupInfo, err := d.combinedDomainStats(tt.domainsMon) + if (err != nil) != tt.wantErr { + t.Errorf("combinedDomainStats() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotStats, tt.wantStats) { + t.Errorf("combinedDomainStats() gotStats = %v, want %v", gotStats, tt.wantStats) + } + if !reflect.DeepEqual(gotGroupInfo, tt.wantGroupInfo) { + t.Errorf("combinedDomainStats() gotGroupInfo = %v, want %v", gotGroupInfo, tt.wantGroupInfo) + } + }) + } +} + +func Test_priorityGroupDecorator_splitPlan(t *testing.T) { + t.Parallel() + tests := []struct { + name string + mbPlan *plan.MBPlan + groupInfos *groupInfo + want *plan.MBPlan + }{ + { + name: "no combined groups - no change", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000, 1: 4_000}, + "machine-60": {2: 6_000, 3: 5_500}, + }, + }, + groupInfos: &groupInfo{ + DomainGroups: map[int]domainGroupMapping{ + 0: {}, + 1: {}, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000, 1: 4_000}, + "machine-60": {2: 6_000, 3: 5_500}, + }, + }, + }, + { + name: "single combined group - split to original groups", + mbPlan: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "combined-9000": {0: 5_000, 1: 4_000}, + }, + }, + groupInfos: &groupInfo{ + DomainGroups: map[int]domainGroupMapping{ + 0: { + "combined-9000": { + "dedicated-60": {0: struct{}{}}, + "machine-60": {1: struct{}{}}, + }, + }, + }, + }, + want: &plan.MBPlan{ + MBGroups: map[string]plan.GroupCCDPlan{ + "dedicated-60": {0: 5_000}, + "machine-60": {1: 4_000}, + }, + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &priorityGroupDecorator{} + got := d.splitPlan(tt.mbPlan, tt.groupInfos) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("splitPlan() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index 5c9d60bb2e..c8ceb81737 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -24,6 +24,7 @@ import ( "golang.org/x/exp/maps" "k8s.io/apimachinery/pkg/util/sets" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/priority" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/resource" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" @@ -127,7 +128,7 @@ func getGroupIncomingInfo(capacity int, incomingStats monitor.GroupMBStats) *res CapacityInMB: capacity, } - result.GroupSorted = sortGroups(maps.Keys(incomingStats)) + result.GroupSorted = priority.GetInstance().SortGroups(maps.Keys(incomingStats)) result.GroupTotalUses = getUsedTotalByGroup(incomingStats) result.FreeInMB, result.GroupLimits = getLimitsByGroupSorted(capacity, result.GroupSorted, result.GroupTotalUses) result.ResourceState = resource.GetResourceState(capacity, result.FreeInMB) @@ -138,18 +139,18 @@ func getGroupIncomingInfo(capacity int, incomingStats monitor.GroupMBStats) *res func groupByWeight[T any](stats map[string]T) map[int][]string { groups := make(map[int][]string, len(stats)) for group := range stats { - weight := getWeight(group) + weight := priority.GetInstance().GetWeight(group) groups[weight] = append(groups[weight], group) } return groups } // preProcessGroupInfo combines groups with same priority together -func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, monitor.DomainGroupMapping, error) { +func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, domainGroupMapping, error) { groups := groupByWeight(stats) result := make(monitor.GroupMBStats) - groupInfos := monitor.DomainGroupMapping{} + groupInfos := domainGroupMapping{} for weight, equivGroups := range groups { if len(equivGroups) == 1 { @@ -158,7 +159,7 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, moni } newKey := fmt.Sprintf("combined-%d", weight) - groupInfo := monitor.CombinedGroupMapping{} + groupInfo := combinedGroupMapping{} combined := make(monitor.GroupMB) maxMap := make(map[int]int) @@ -174,7 +175,7 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, moni // Second pass: validate and build CCD sets for each group (only within equivGroups) for _, group := range equivGroups { - ccdSet := monitor.CCDSet{} + ccdSet := ccdSet{} for id, mbStat := range stats[group] { // skip shared ccd with similar incoming data if mbStat.TotalMB > maxMap[id]/2 && mbStat.TotalMB < maxMap[id] { diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go index cdb33b42b5..7fd29bbb43 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper_test.go @@ -22,11 +22,16 @@ import ( "k8s.io/apimachinery/pkg/util/sets" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/priority" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/resource" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" ) +func init() { + priority.GetInstance().AddWeight("machine", 9_000) +} + func Test_maskPlanWithNoThrottles(t *testing.T) { t.Parallel() type args struct { @@ -187,33 +192,9 @@ func Test_preProcessGroupInfo(t *testing.T) { name string stats monitor.GroupMBStats wantResult monitor.GroupMBStats - wantGroupInfos monitor.DomainGroupMapping + wantGroupInfos domainGroupMapping wantErr bool }{ - { - name: "empty stats", - stats: monitor.GroupMBStats{}, - wantResult: monitor.GroupMBStats{}, - wantGroupInfos: monitor.DomainGroupMapping{}, - wantErr: false, - }, - { - name: "single group - no combination needed", - stats: monitor.GroupMBStats{ - "dedicated": { - 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - }, - wantResult: monitor.GroupMBStats{ - "dedicated": { - 0: {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - }, - wantGroupInfos: monitor.DomainGroupMapping{}, - wantErr: false, - }, { name: "two groups with different weights - no combination", stats: monitor.GroupMBStats{ @@ -232,7 +213,7 @@ func Test_preProcessGroupInfo(t *testing.T) { 1: {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, }, }, - wantGroupInfos: monitor.DomainGroupMapping{}, + wantGroupInfos: domainGroupMapping{}, wantErr: false, }, { @@ -251,66 +232,7 @@ func Test_preProcessGroupInfo(t *testing.T) { 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, }, }, - wantGroupInfos: monitor.DomainGroupMapping{ - "combined-9000": { - "dedicated": {0: struct{}{}}, - "machine": {1: struct{}{}}, - }, - }, - wantErr: false, - }, - { - name: "three groups with same weight - combine into one", - stats: monitor.GroupMBStats{ - "dedicated": { - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine": { - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "system": { - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - wantResult: monitor.GroupMBStats{ - "combined-9000": { - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - wantGroupInfos: monitor.DomainGroupMapping{ - "combined-9000": { - "dedicated": {0: struct{}{}}, - "machine": {1: struct{}{}}, - "system": {2: struct{}{}}, - }, - }, - wantErr: false, - }, - { - name: "mixed groups - some combined some not", - stats: monitor.GroupMBStats{ - "dedicated": { - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine": { - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "share-50": { - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - wantResult: monitor.GroupMBStats{ - "combined-9000": { - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "share-50": { - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - wantGroupInfos: monitor.DomainGroupMapping{ + wantGroupInfos: domainGroupMapping{ "combined-9000": { "dedicated": {0: struct{}{}}, "machine": {1: struct{}{}}, @@ -345,26 +267,6 @@ func Test_preProcessGroupSumStat(t *testing.T) { sumStats map[string][]monitor.MBInfo want map[string][]monitor.MBInfo }{ - { - name: "empty stats", - sumStats: map[string][]monitor.MBInfo{}, - want: map[string][]monitor.MBInfo{}, - }, - { - name: "single group - no combination needed", - sumStats: map[string][]monitor.MBInfo{ - "dedicated": { - {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - }, - want: map[string][]monitor.MBInfo{ - "dedicated": { - {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - }, - }, { name: "two groups with different weights - no combination", sumStats: map[string][]monitor.MBInfo{ @@ -407,72 +309,6 @@ func Test_preProcessGroupSumStat(t *testing.T) { }, }, }, - { - name: "three groups with same weight - combine and sum all", - sumStats: map[string][]monitor.MBInfo{ - "dedicated": { - {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - "machine": { - {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, - {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, - }, - "system": { - {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, - {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, - }, - }, - want: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - {LocalMB: 7_000, RemoteMB: 3_500, TotalMB: 10_500}, - }, - }, - }, - { - name: "mixed groups - some combined some not", - sumStats: map[string][]monitor.MBInfo{ - "dedicated": { - {LocalMB: 5_000, RemoteMB: 3_000, TotalMB: 8_000}, - {LocalMB: 4_000, RemoteMB: 2_000, TotalMB: 6_000}, - }, - "machine": { - {LocalMB: 3_000, RemoteMB: 1_000, TotalMB: 4_000}, - {LocalMB: 2_000, RemoteMB: 1_000, TotalMB: 3_000}, - }, - "share-50": { - {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, - {LocalMB: 800, RemoteMB: 400, TotalMB: 1_200}, - }, - }, - want: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - "share-50": { - {LocalMB: 1_000, RemoteMB: 500, TotalMB: 1_500}, - {LocalMB: 800, RemoteMB: 400, TotalMB: 1_200}, - }, - }, - }, - { - name: "single domain stats", - sumStats: map[string][]monitor.MBInfo{ - "dedicated": { - {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine": { - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - want: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, - }, - }, - }, } for _, tt := range tests { tt := tt diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go deleted file mode 100644 index 411a0ddf28..0000000000 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_test.go +++ /dev/null @@ -1,1849 +0,0 @@ -package advisor - -import ( - "context" - "reflect" - "testing" - - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/adjuster" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/distributor" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/quota" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/sankey" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" - "github.com/kubewharf/katalyst-core/pkg/metrics" - "k8s.io/apimachinery/pkg/util/sets" -) - -func Test_EnhancedAdvisor_GetPlan(t *testing.T) { - t.Parallel() - type fields struct { - domains domain.Domains - defaultDomainCapacity int - XDomGroups sets.String - GroupCapacityInMB map[string]int - quotaStrategy quota.Decider - flower sankey.DomainFlower - adjusters map[string]adjuster.Adjuster - } - type args struct { - ctx context.Context - domainsMon *monitor.DomainStats - } - tests := []struct { - name string - fields fields - args args - want *plan.MBPlan - wantErr bool - }{ - { - name: "same priority with not enough capacity for two and a higher priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "/-100": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 4250, 3: 4250}, - "machine-60": {1: 4250, 4: 4250}, - "/-100": {2: 20_000, 5: 20_000}, - }}, - wantErr: false, - }, - { - name: "same priority with not enough capacity for two and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 14_250, 3: 14_250}, - "machine-60": {1: 14_250, 4: 14_250}, - "share-50": {2: 0, 5: 0}, - }}, - wantErr: false, - }, - { - name: "same priority with not enough capacity for one and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 10_000, - RemoteMB: 10_000, - TotalMB: 20_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 20_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - 1: { - LocalMB: 20_000, - RemoteMB: 20_000, - TotalMB: 40_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 0, - TotalMB: 10_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 14_250, 3: 14_250}, - "machine-60": {1: 14_250, 4: 14_250}, - "share-50": {2: 0, 5: 0}, - }}, - wantErr: false, - }, - { - name: "same priority with partial enough capacity and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": { - 0: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - 1: { - LocalMB: 10_000, - RemoteMB: 5_000, - TotalMB: 15_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, - "share-50": {2: 8500, 5: 8500}, - }}, - wantErr: false, - }, - { - name: "same priority with fully enough capacity and a lower priority", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": { - 0: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, - "share-50": {2: 10_000, 5: 10_000}, - }}, - wantErr: false, - }, - { - name: "same priority with shared ccd", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 4: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 4: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 500, - RemoteMB: 500, - TotalMB: 1000, - }, - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 5_500, - RemoteMB: 5_500, - TotalMB: 11_000, - }, - 1: { - LocalMB: 5_500, - RemoteMB: 5_500, - TotalMB: 11_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 5_500, - RemoteMB: 5_500, - TotalMB: 11_000, - }, - 1: { - LocalMB: 5_500, - RemoteMB: 5_500, - TotalMB: 11_000, - }, - }, - "share-50": { - 0: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - }, - want: &plan.MBPlan{MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 15_000, 3: 15_000}, - "machine-60": {1: 15_000, 4: 15_000}, - "share-50": {2: 10_000, 5: 10_000}, - }}, - wantErr: false, - }, - { - name: "invalid incomings with shared ccd", - fields: fields{ - domains: domain.Domains{ - 0: domain.NewDomain(0, sets.NewInt(0, 1, 2), 88888), - 1: domain.NewDomain(1, sets.NewInt(3, 4, 5), 88888), - }, - defaultDomainCapacity: 30_000, - XDomGroups: nil, - GroupCapacityInMB: nil, - quotaStrategy: quota.New(), - flower: sankey.New(), - adjusters: map[string]adjuster.Adjuster{}, - }, - args: args{ - ctx: context.TODO(), - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 4: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 1: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 0: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 2: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - 4: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: { - LocalMB: 4_000, - RemoteMB: 5_000, - TotalMB: 9_000, - }, - 4: { - LocalMB: 5_000, - RemoteMB: 5_000, - TotalMB: 10_000, - }, - }, - "share-50": map[int]monitor.MBInfo{ - 5: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - 0: { - LocalMB: 9_000, - RemoteMB: 10_000, - TotalMB: 19_000, - }, - 1: { - LocalMB: 9_000, - RemoteMB: 10_000, - TotalMB: 19_000, - }, - }, - "machine-60": { - 0: { - LocalMB: 9_000, - RemoteMB: 10_000, - TotalMB: 19_000, - }, - 1: { - LocalMB: 9_000, - RemoteMB: 10_000, - TotalMB: 19_000, - }, - }, - "share-50": { - 0: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - 1: { - LocalMB: 5_000, - RemoteMB: 0, - TotalMB: 5_000, - }, - }, - }, - }, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - d := &domainAdvisor{ - domains: tt.fields.domains, - defaultDomainCapacity: tt.fields.defaultDomainCapacity, - capPercent: 100, - xDomGroups: tt.fields.XDomGroups, - groupCapacityInMB: tt.fields.GroupCapacityInMB, - quotaStrategy: tt.fields.quotaStrategy, - flower: tt.fields.flower, - adjusters: tt.fields.adjusters, - ccdDistribute: distributor.New(0, 20_000), - emitter: &metrics.DummyMetrics{}, - } - advisor := &EnhancedAdvisor{inner: *d} - got, err := advisor.GetPlan(tt.args.ctx, tt.args.domainsMon) - if (err != nil) != tt.wantErr { - t.Errorf("GetPlan() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetPlan() got = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_EnhancedAdvisor_combinedDomainStats(t *testing.T) { - t.Parallel() - tests := []struct { - name string - domainsMon *monitor.DomainStats - wantStats *monitor.DomainStats - wantGroupInfo *monitor.GroupInfo - wantErr bool - }{ - { - name: "single group per weight - no combination", - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, - }, - }, - 1: { - "share-50": map[int]monitor.MBInfo{ - 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, - }, - }, - 1: { - "share-50": map[int]monitor.MBInfo{ - 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, - }, - "share-50": { - {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - wantStats: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, - }, - }, - 1: { - "share-50": map[int]monitor.MBInfo{ - 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - 1: {LocalMB: 3_000, RemoteMB: 2_000, TotalMB: 5_000}, - }, - }, - 1: { - "share-50": map[int]monitor.MBInfo{ - 2: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - {LocalMB: 5_000, RemoteMB: 5_000, TotalMB: 10_000}, - {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, - }, - "share-50": { - {LocalMB: 0, RemoteMB: 0, TotalMB: 0}, - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - wantGroupInfo: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: {}, - 1: {}, - }, - }, - wantErr: false, - }, - { - name: "multiple groups with same weight - combine groups", - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": { - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - wantStats: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, - }, - }, - }, - wantGroupInfo: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - }, - }, - wantErr: false, - }, - { - name: "multiple domains with same weight groups", - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - 1: { - "dedicated-60": map[int]monitor.MBInfo{ - 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, - }, - "machine-60": { - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, - }, - }, - }, - wantStats: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - 1: { - "combined-9000": map[int]monitor.MBInfo{ - 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, - 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - }, - 1: { - "combined-9000": map[int]monitor.MBInfo{ - 2: {LocalMB: 12_000, RemoteMB: 6_000, TotalMB: 18_000}, - 3: {LocalMB: 7_000, RemoteMB: 3_000, TotalMB: 10_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 18_000, RemoteMB: 9_000, TotalMB: 27_000}, - {LocalMB: 19_000, RemoteMB: 9_000, TotalMB: 28_000}, - }, - }, - }, - wantGroupInfo: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - 1: { - "combined-9000": { - "dedicated-60": {2: struct{}{}}, - "machine-60": {3: struct{}{}}, - }, - }, - }, - }, - wantErr: false, - }, - { - name: "three groups with same weight", - domainsMon: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "system-60": map[int]monitor.MBInfo{ - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "dedicated-60": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": map[int]monitor.MBInfo{ - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "system-60": map[int]monitor.MBInfo{ - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "dedicated-60": { - {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - }, - "machine-60": { - {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - }, - "system-60": { - {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - }, - wantStats: &monitor.DomainStats{ - Incomings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - }, - Outgoings: map[int]monitor.GroupMBStats{ - 0: { - "combined-9000": map[int]monitor.MBInfo{ - 0: {LocalMB: 10_000, RemoteMB: 5_000, TotalMB: 15_000}, - 1: {LocalMB: 8_000, RemoteMB: 4_000, TotalMB: 12_000}, - 2: {LocalMB: 6_000, RemoteMB: 3_000, TotalMB: 9_000}, - }, - }, - }, - OutgoingGroupSumStat: map[string][]monitor.MBInfo{ - "combined-9000": { - {LocalMB: 24_000, RemoteMB: 12_000, TotalMB: 36_000}, - }, - }, - }, - wantGroupInfo: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - "system-60": {2: struct{}{}}, - }, - }, - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - d := &EnhancedAdvisor{} - gotStats, gotGroupInfo, err := d.combinedDomainStats(tt.domainsMon) - if (err != nil) != tt.wantErr { - t.Errorf("combinedDomainStats() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(gotStats, tt.wantStats) { - t.Errorf("combinedDomainStats() gotStats = %v, want %v", gotStats, tt.wantStats) - } - if !reflect.DeepEqual(gotGroupInfo, tt.wantGroupInfo) { - t.Errorf("combinedDomainStats() gotGroupInfo = %v, want %v", gotGroupInfo, tt.wantGroupInfo) - } - }) - } -} - -func Test_EnhancedAdvisor_splitPlan(t *testing.T) { - t.Parallel() - tests := []struct { - name string - mbPlan *plan.MBPlan - groupInfos *monitor.GroupInfo - want *plan.MBPlan - }{ - { - name: "no combined groups - no change", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000, 1: 4_000}, - "machine-60": {2: 6_000, 3: 5_500}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: {}, - 1: {}, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000, 1: 4_000}, - "machine-60": {2: 6_000, 3: 5_500}, - }, - }, - }, - { - name: "single combined group - split to original groups", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000}, - "machine-60": {1: 4_000}, - }, - }, - }, - { - name: "mixed combined and non-combined groups", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000}, - "share-50": {2: 8_000, 3: 7_000}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000}, - "machine-60": {1: 4_000}, - "share-50": {2: 8_000, 3: 7_000}, - }, - }, - }, - { - name: "multiple combined groups in different domains", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000, 2: 6_000, 3: 5_500}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - 1: { - "combined-9000": { - "dedicated-60": {2: struct{}{}}, - "machine-60": {3: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000, 2: 6_000}, - "machine-60": {1: 4_000, 3: 5_500}, - }, - }, - }, - { - name: "combined group with partial CCD match", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000, 2: 3_000}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000}, - "machine-60": {1: 4_000}, - }, - }, - }, - { - name: "multiple combined groups with different priorities", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000}, - "combined-1050": {2: 8_000, 3: 7_000}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - }, - "combined-1050": { - "share-50": {2: struct{}{}}, - "share-alt-50": {3: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000}, - "machine-60": {1: 4_000}, - "share-50": {2: 8_000}, - "share-alt-50": {3: 7_000}, - }, - }, - }, - { - name: "empty group info - remove combined groups", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{}, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{}, - }, - }, - { - name: "three groups combined and split", - mbPlan: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "combined-9000": {0: 5_000, 1: 4_000, 2: 3_500}, - }, - }, - groupInfos: &monitor.GroupInfo{ - DomainGroups: map[int]monitor.DomainGroupMapping{ - 0: { - "combined-9000": { - "dedicated-60": {0: struct{}{}}, - "machine-60": {1: struct{}{}}, - "system-60": {2: struct{}{}}, - }, - }, - }, - }, - want: &plan.MBPlan{ - MBGroups: map[string]plan.GroupCCDPlan{ - "dedicated-60": {0: 5_000}, - "machine-60": {1: 4_000}, - "system-60": {2: 3_500}, - }, - }, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - d := &EnhancedAdvisor{} - got := d.splitPlan(tt.mbPlan, tt.groupInfos) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("splitPlan() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go index 56ace05b0b..40f83dc38b 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go +++ b/pkg/agent/qrm-plugins/mb/advisor/distributor/types.go @@ -16,7 +16,11 @@ limitations under the License. package distributor -import "math" +import ( + "math" + + "github.com/kubewharf/katalyst-core/pkg/util/general" +) type Distributor interface { // Distribute distributes total mb into ccds by their relative weights @@ -24,6 +28,7 @@ type Distributor interface { } func New(min, max int) Distributor { + general.Infof("mbm: ccd distributor is composite of logarithmic and linear, with min %v, max %v", min, max) return &logarithmicBoundedDistributor{ inner: &linearBoundedDistributor{ min: min, diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go index e3c25d562f..21079d9513 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go @@ -99,19 +99,28 @@ func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainS groupedDomOutgoings := domainsMon.OutgoingGroupSumStat groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, groupedDomOutgoings, d.capPercent) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] group-domain outgoing quotas: %s", + general.InfofV(6, "[mbm] [advisor] group-domain outgoing quotas adjusted: %s", stringify(groupedDomainOutgoingQuotas)) } d.emitAdjustedOutgoingTargets(groupedDomainOutgoingQuotas) // split outgoing mb to ccd level groupedCCDOutgoingQuotas := d.distributeToCCDs(ctx, groupedDomainOutgoingQuotas, domainsMon.Outgoings) + if klog.V(6).Enabled() { + general.InfofV(6, "[mbm] [advisor] group-ccd outgoing quotas: %v", groupedCCDOutgoingQuotas) + } rawPlan := convertToPlan(groupedCCDOutgoingQuotas) + if klog.V(6).Enabled() { + general.InfofV(6, "[mbm] [advisor] raw plan: %s", rawPlan) + } d.emitRawPlan(rawPlan) // finalize plan with never-throttle groups and ccb mb checks checkedPlan := applyPlanCCDBoundsChecks(rawPlan, d.ccdMinMB, d.ccdMaxMB) updatePlan := maskPlanWithNoThrottles(checkedPlan, d.groupNeverThrottles, d.getNoThrottleMB()) + if klog.V(6).Enabled() { + general.InfofV(6, "[mbm] [advisor] mb plan update: %s", updatePlan) + } d.emitUpdatePlan(updatePlan) return updatePlan, nil @@ -262,6 +271,10 @@ func (d *domainAdvisor) domainDistributeGroup(domID int, group string, weights[ccd] = stat.TotalMB } domCCDQuotas := d.ccdDistribute.Distribute(domTotal, weights) + if klog.V(6).Enabled() { + general.InfofV(6, "[mbm] [advisor] domain %d, group %s, total %v, weights %v, distribute to ccd quotas: %v", + domID, group, domTotal, weights, domCCDQuotas) + } result := map[int]int{} for ccd, v := range domCCDQuotas { result[ccd] = v diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go index 5c3ba41968..6362a4214c 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go @@ -216,7 +216,7 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { "share-60": 6_000, "share-50": 6_000 - 2_200, }, - ResourceState: resource.State("underStress"), + ResourceState: resource.State("stressful"), }, }, wantErr: false, diff --git a/pkg/agent/qrm-plugins/mb/advisor/priority/group_priority.go b/pkg/agent/qrm-plugins/mb/advisor/priority/group_priority.go new file mode 100644 index 0000000000..a92598bbeb --- /dev/null +++ b/pkg/agent/qrm-plugins/mb/advisor/priority/group_priority.go @@ -0,0 +1,101 @@ +/* +Copyright 2022 The Katalyst 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. +*/ + +package priority + +import ( + "fmt" + "sort" + "sync" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/sets" + + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/resource" + "github.com/kubewharf/katalyst-core/pkg/util/general" +) + +var ( + instance GroupPriority + once sync.Once +) + +func GetInstance() GroupPriority { + once.Do(func() { + instance = make(GroupPriority, len(resctrlMajorGroupWeights)) + for key, value := range resctrlMajorGroupWeights { + instance[key] = value + } + }) + return instance +} + +type GroupPriority map[string]int + +func (g GroupPriority) GetWeight(name string) int { + baseWeight, ok := g[getMajor(name)] + if !ok { + return defaultWeight + } + + return baseWeight + getSubWeight(name) +} + +func (g GroupPriority) SortGroups(groups []string) []sets.String { + sort.Slice(groups, func(i, j int) bool { + return g.GetWeight(groups[i]) > g.GetWeight(groups[j]) + }) + + return g.mergeGroupsByWeight(groups) +} + +func (g GroupPriority) mergeGroupsByWeight(groups []string) []sets.String { + var mergedGroups []sets.String + for _, group := range groups { + if len(mergedGroups) == 0 { + mergedGroups = append(mergedGroups, sets.NewString(group)) + continue + } + + lastGroup := mergedGroups[len(mergedGroups)-1] + weightLastGroup, err := g.getWeightOfEquivGroup(lastGroup) + if err != nil { + general.Warningf("[mbm] failed to get allocation weight of group %v: %v", lastGroup, err) + continue + } + + if g.GetWeight(group) == weightLastGroup { + lastGroup.Insert(group) + continue + } + + mergedGroups = append(mergedGroups, sets.NewString(group)) + } + return mergedGroups +} + +func (g GroupPriority) getWeightOfEquivGroup(equivGroups sets.String) (int, error) { + repGroup, err := resource.GetGroupRepresentative(equivGroups) + if err != nil { + return 0, errors.Wrap(err, fmt.Sprintf("failed to get representative of groups %v", equivGroups)) + } + + return g.GetWeight(repGroup), nil +} + +func (g GroupPriority) AddWeight(name string, weight int) { + g[name] = weight +} diff --git a/pkg/agent/qrm-plugins/mb/advisor/group_sort.go b/pkg/agent/qrm-plugins/mb/advisor/priority/group_sort.go similarity index 51% rename from pkg/agent/qrm-plugins/mb/advisor/group_sort.go rename to pkg/agent/qrm-plugins/mb/advisor/priority/group_sort.go index 2195048ade..9fed4c809c 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/group_sort.go +++ b/pkg/agent/qrm-plugins/mb/advisor/priority/group_sort.go @@ -14,24 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -package advisor +package priority import ( - "fmt" - "sort" "strconv" "strings" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/sets" - - "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/resource" "github.com/kubewharf/katalyst-core/pkg/consts" - "github.com/kubewharf/katalyst-core/pkg/util/general" ) const defaultWeight = 5_000 +// resctrlMajorGroupWeights is initialized with built-in resctrl groups and their priorities var resctrlMajorGroupWeights = map[string]int{ consts.ResctrlGroupRoot: 10_000, // intrinsic root the highest consts.ResctrlGroupDedicated: 9_000, @@ -72,56 +66,3 @@ func getSubWeight(name string) int { return 0 } - -func getWeight(name string) int { - baseWeight, ok := resctrlMajorGroupWeights[getMajor(name)] - if !ok { - return defaultWeight - } - - return baseWeight + getSubWeight(name) -} - -// sortGroups sorts groups by their weights in desc order; -// groups having identical weight put in one set -func sortGroups(groups []string) []sets.String { - sort.Slice(groups, func(i, j int) bool { - return getWeight(groups[i]) > getWeight(groups[j]) - }) - - return mergeGroupsByWeight(groups) -} - -func mergeGroupsByWeight(groups []string) []sets.String { - var mergedGroups []sets.String - for _, group := range groups { - if len(mergedGroups) == 0 { - mergedGroups = append(mergedGroups, sets.NewString(group)) - continue - } - - lastGroup := mergedGroups[len(mergedGroups)-1] - weightLastGroup, err := getWeightOfEquivGroup(lastGroup) - if err != nil { - general.Warningf("[mbm] failed to get allocation weight of group %v: %v", lastGroup, err) - continue - } - - if getWeight(group) == weightLastGroup { - lastGroup.Insert(group) - continue - } - - mergedGroups = append(mergedGroups, sets.NewString(group)) - } - return mergedGroups -} - -func getWeightOfEquivGroup(equivGroups sets.String) (int, error) { - repGroup, err := resource.GetGroupRepresentative(equivGroups) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("failed to get representative of groups %v", equivGroups)) - } - - return getWeight(repGroup), nil -} diff --git a/pkg/agent/qrm-plugins/mb/advisor/group_sort_test.go b/pkg/agent/qrm-plugins/mb/advisor/priority/group_sort_test.go similarity index 93% rename from pkg/agent/qrm-plugins/mb/advisor/group_sort_test.go rename to pkg/agent/qrm-plugins/mb/advisor/priority/group_sort_test.go index af63f0da51..e4bfdad1fd 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/group_sort_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/priority/group_sort_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package advisor +package priority import ( "reflect" @@ -63,7 +63,7 @@ func Test_getSortedGroups(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - if got := sortGroups(tt.args.groups); !reflect.DeepEqual(got, tt.want) { + if got := GetInstance().SortGroups(tt.args.groups); !reflect.DeepEqual(got, tt.want) { t.Errorf("sortGroups() = %v, want %v", got, tt.want) } }) diff --git a/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go b/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go index 525ae61db4..8f3c039bdb 100644 --- a/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go +++ b/pkg/agent/qrm-plugins/mb/monitor/domain_stat.go @@ -40,20 +40,6 @@ type DomainStats struct { // DomainMonStat is memory bandwidth statistic info of one domain, each has multiple groups type DomainMonStat = GroupMBStats -// GroupInfo stores the mapping of groups and their CCDs for each domain -type GroupInfo struct { // DomainGroups maps domain ID -> combined group key -> original group key -> CCD IDs - DomainGroups map[int]DomainGroupMapping -} - -// DomainGroupMapping maps combined group keys to their original groups -type DomainGroupMapping map[string]CombinedGroupMapping - -// CombinedGroupMapping maps original group keys to their CCD IDs -type CombinedGroupMapping map[string]CCDSet - -// CCDSet represents a set of CCD IDs -type CCDSet map[int]struct{} - // NewDomainStats splits group-style outgoing mb stat (as from resctrl mon-data) into corresponding domains, // and attributes incoming traffic from outgoings for the cross-domain groups func NewDomainStats(statOutgoing GroupMBStats, ccdToDomain map[int]int, xDomGroups sets.String) (*DomainStats, error) { diff --git a/pkg/agent/qrm-plugins/mb/policy/plugin.go b/pkg/agent/qrm-plugins/mb/policy/plugin.go index a115befd57..9927cd0689 100644 --- a/pkg/agent/qrm-plugins/mb/policy/plugin.go +++ b/pkg/agent/qrm-plugins/mb/policy/plugin.go @@ -32,6 +32,7 @@ import ( "github.com/kubewharf/katalyst-core/cmd/katalyst-agent/app/agent" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/advisor/priority" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/allocator" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" @@ -119,13 +120,23 @@ func (m *MBPlugin) Start() (err error) { return nil } + // ensure the extra resctrl groups registered with their priorities + for group, weight := range m.conf.ExtraGroupPriorities { + general.Infof("mbm: registering extra group %s, priority %d", group, weight) + priority.GetInstance().AddWeight(group, weight) + } + // initializing advisor field is deferred as qos group mb capacities is known now - m.advisor = advisor.NewEnhancedAdvisor(m.emitter, m.domains, + general.Infof("mbm: create traditional advior") + m.advisor = advisor.NewDomainAdvisor(m.emitter, m.domains, m.conf.MinCCDMB, m.conf.MaxCCDMB, defaultMBDomainCapacity, m.conf.MBCapLimitPercent, m.conf.CrossDomainGroups, m.conf.MBQRMPluginConfig.NoThrottleGroups, - groupCapacities, - ) + groupCapacities) + if !m.conf.GroupPriorityUnique { + general.Infof("mbm: use enhanced advior able to treat multiple resctrl groups with identical priority") + m.advisor = advisor.DecorateByPriorityGroup(m.advisor) + } go func() { wait.Until(m.run, interval, m.chStop) diff --git a/pkg/config/agent/qrm/mb_plugin.go b/pkg/config/agent/qrm/mb_plugin.go index bb2472504c..73206e78a9 100644 --- a/pkg/config/agent/qrm/mb_plugin.go +++ b/pkg/config/agent/qrm/mb_plugin.go @@ -38,6 +38,8 @@ type MBQRMPluginConfig struct { ResetResctrlOnly bool LocalIsVictimAndTotalIsAllRead bool + GroupPriorityUnique bool + ExtraGroupPriorities map[string]int } func NewMBQRMPluginConfig() *MBQRMPluginConfig { diff --git a/pkg/consts/resctrl.go b/pkg/consts/resctrl.go index 7dd102fe30..8d54030ffe 100644 --- a/pkg/consts/resctrl.go +++ b/pkg/consts/resctrl.go @@ -22,7 +22,6 @@ const ( ResctrlGroupRoot = "/" ResctrlGroupDedicated = "dedicated" ResctrlGroupSystem = "system" - ResctrlGroupMachine = "machine" ResctrlGroupShare = "share" ResctrlGroupReclaim = "reclaim" From 12678506681e5688e79a7704fe4864fcfb08f9b3 Mon Sep 17 00:00:00 2001 From: Hongwei Chen Date: Tue, 7 Apr 2026 06:22:57 +0000 Subject: [PATCH 09/10] minor refactor: functions naming combined groups --- .../mb/advisor/advisor_decorator.go | 3 +-- .../qrm-plugins/mb/advisor/advisor_helper.go | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go index 56dd53510c..f658dfaab9 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go @@ -18,7 +18,6 @@ package advisor import ( "context" - "strings" "k8s.io/apimachinery/pkg/util/sets" @@ -87,7 +86,7 @@ func (d *priorityGroupDecorator) combinedDomainStats(domainsMon *monitor.DomainS func (d *priorityGroupDecorator) splitPlan(mbPlan *plan.MBPlan, groupInfos *groupInfo) *plan.MBPlan { for groupKey, ccdPlan := range mbPlan.MBGroups { - if !strings.Contains(groupKey, "combined-") { + if !isCombinedGroup(groupKey) { continue } for _, domainGroupInfos := range groupInfos.DomainGroups { diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index c8ceb81737..fbe0611170 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -30,6 +30,8 @@ import ( "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" ) +const combinedGroupPrefix = "combined-" + // getMinEffectiveCapacity identifies the min dynamic capacity required by pre-defined groups, // if the specific groups have active MB traffics func getMinEffectiveCapacity(base int, groupCaps map[string]int, incomingStats monitor.GroupMBStats) int { @@ -206,8 +208,11 @@ func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]m continue } - newKey := fmt.Sprintf("combined-%d", weight) - sumList := make([]monitor.MBInfo, len(sumStats[equivGroups[0]])) + newKey := getCombinedGroupKey(weight) + // sumStats holds outgoing summary of each domain for each group, in other words, + // each slot of sumStats has uniform shape: slice with length of domain number + numDomains := len(sumStats[equivGroups[0]]) + sumList := make([]monitor.MBInfo, numDomains) for _, group := range equivGroups { for id, stat := range sumStats[group] { @@ -222,6 +227,15 @@ func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]m return result } +func getCombinedGroupKey(weight int) string { + newKey := fmt.Sprintf("%s%d", combinedGroupPrefix, weight) + return newKey +} + +func isCombinedGroup(groupName string) bool { + return strings.Contains(groupName, combinedGroupPrefix) +} + func getLimitsByGroupSorted(capacity int, groupSorting []sets.String, groupUsages map[string]int) (int, map[string]int) { result := make(map[string]int) From b31c94e6ecc18337581020ddc60dad56eda09f25 Mon Sep 17 00:00:00 2001 From: Hongwei Chen Date: Tue, 7 Apr 2026 18:46:19 +0000 Subject: [PATCH 10/10] refactor: policy uses the advisor able to process groups of identical priority --- .../app/options/qrm/mb_plugin.go | 4 - .../qrm-plugins/mb/advisor/advisor_helper.go | 5 +- ..._advisor_metrics.go => advisor_metrics.go} | 48 ++++---- ...visor_decorator.go => priority_advisor.go} | 35 ++++-- ...rator_test.go => priority_advisor_test.go} | 4 +- ...in_advisor.go => uniq_priority_advisor.go} | 110 +++++++++--------- ..._test.go => uniq_priority_advisor_test.go} | 6 +- pkg/agent/qrm-plugins/mb/policy/plugin.go | 8 +- pkg/config/agent/qrm/mb_plugin.go | 1 - 9 files changed, 112 insertions(+), 109 deletions(-) rename pkg/agent/qrm-plugins/mb/advisor/{domain_advisor_metrics.go => advisor_metrics.go} (61%) rename pkg/agent/qrm-plugins/mb/advisor/{advisor_decorator.go => priority_advisor.go} (68%) rename pkg/agent/qrm-plugins/mb/advisor/{advisor_decorator_test.go => priority_advisor_test.go} (99%) rename pkg/agent/qrm-plugins/mb/advisor/{domain_advisor.go => uniq_priority_advisor.go} (67%) rename pkg/agent/qrm-plugins/mb/advisor/{domain_advisor_test.go => uniq_priority_advisor_test.go} (99%) diff --git a/cmd/katalyst-agent/app/options/qrm/mb_plugin.go b/cmd/katalyst-agent/app/options/qrm/mb_plugin.go index ec00e05fac..788b07e51e 100644 --- a/cmd/katalyst-agent/app/options/qrm/mb_plugin.go +++ b/cmd/katalyst-agent/app/options/qrm/mb_plugin.go @@ -52,7 +52,6 @@ type MBOptions struct { CrossDomainGroups []string ResetResctrlOnly bool LocalIsVictimAndTotalIsAllRead bool - GroupPriorityUnique bool ExtraGroupPriorities map[string]int } @@ -91,8 +90,6 @@ func (o *MBOptions) AddFlags(fss *cliflag.NamedFlagSets) { o.ResetResctrlOnly, "not to run mb plugin really, and only reset to ensure resctrl FS in default status") fs.BoolVar(&o.LocalIsVictimAndTotalIsAllRead, "mb-local-is-victim", o.LocalIsVictimAndTotalIsAllRead, "turn resctrl local as victim") - fs.BoolVar(&o.GroupPriorityUnique, "mb-group-priority-unique", - o.GroupPriorityUnique, "use equality groups enhanced mb advisor") fs.StringToIntVar(&o.ExtraGroupPriorities, "mb-extra-group-priorities", o.ExtraGroupPriorities, "extra resctrl groups with priorities") } @@ -109,7 +106,6 @@ func (o *MBOptions) ApplyTo(conf *qrm.MBQRMPluginConfig) error { conf.DomainGroupAwareCapacityPCT = o.DomainGroupAwareCapacityPCT conf.ResetResctrlOnly = o.ResetResctrlOnly conf.LocalIsVictimAndTotalIsAllRead = o.LocalIsVictimAndTotalIsAllRead - conf.GroupPriorityUnique = o.GroupPriorityUnique conf.ExtraGroupPriorities = o.ExtraGroupPriorities return nil } diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go index fbe0611170..7494c454ea 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_helper.go @@ -160,7 +160,7 @@ func preProcessGroupInfo(stats monitor.GroupMBStats) (monitor.GroupMBStats, doma continue } - newKey := fmt.Sprintf("combined-%d", weight) + newKey := getCombinedGroupKey(weight) groupInfo := combinedGroupMapping{} combined := make(monitor.GroupMB) maxMap := make(map[int]int) @@ -228,8 +228,7 @@ func preProcessGroupSumStat(sumStats map[string][]monitor.MBInfo) map[string][]m } func getCombinedGroupKey(weight int) string { - newKey := fmt.Sprintf("%s%d", combinedGroupPrefix, weight) - return newKey + return fmt.Sprintf("%s%d", combinedGroupPrefix, weight) } func isCombinedGroup(groupName string) bool { diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_metrics.go b/pkg/agent/qrm-plugins/mb/advisor/advisor_metrics.go similarity index 61% rename from pkg/agent/qrm-plugins/mb/advisor/domain_advisor_metrics.go rename to pkg/agent/qrm-plugins/mb/advisor/advisor_metrics.go index 71fd5e3972..9b9cd7be8c 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_metrics.go +++ b/pkg/agent/qrm-plugins/mb/advisor/advisor_metrics.go @@ -37,31 +37,31 @@ const ( namePlanUpdate = "mbm_plan_update" ) -func (d *domainAdvisor) emitDomIncomingStatSummaryMetrics(domLimits map[int]*resource.MBGroupIncomingStat) { +func (a *uniqPriorityAdvisor) emitDomIncomingStatSummaryMetrics(domLimits map[int]*resource.MBGroupIncomingStat) { for domID, limit := range domLimits { tags := map[string]string{ "domain": fmt.Sprintf("%d", domID), "state": string(limit.ResourceState), } - emitKV(d.emitter, nameMBMCapacity, limit.CapacityInMB, tags) - emitKV(d.emitter, nameMBMFree, limit.FreeInMB, tags) + emitKV(a.emitter, nameMBMCapacity, limit.CapacityInMB, tags) + emitKV(a.emitter, nameMBMFree, limit.FreeInMB, tags) } } -func (d *domainAdvisor) emitStatsMtrics(domainsMon *monitor.DomainStats) { - d.emitOutgoingStats(domainsMon.Outgoings) - d.emitIncomingStats(domainsMon.Incomings) +func (a *uniqPriorityAdvisor) emitStatsMtrics(domainsMon *monitor.DomainStats) { + a.emitOutgoingStats(domainsMon.Outgoings) + a.emitIncomingStats(domainsMon.Incomings) } -func (d *domainAdvisor) emitIncomingStats(incomings map[int]monitor.DomainMonStat) { - d.emitStat(incomings, nameMBMIncomingStat) +func (a *uniqPriorityAdvisor) emitIncomingStats(incomings map[int]monitor.DomainMonStat) { + a.emitStat(incomings, nameMBMIncomingStat) } -func (d *domainAdvisor) emitOutgoingStats(outgoings map[int]monitor.DomainMonStat) { - d.emitStat(outgoings, nameMBMOutgoingStat) +func (a *uniqPriorityAdvisor) emitOutgoingStats(outgoings map[int]monitor.DomainMonStat) { + a.emitStat(outgoings, nameMBMOutgoingStat) } -func (d *domainAdvisor) emitStat(stats map[int]monitor.DomainMonStat, metricName string) { +func (a *uniqPriorityAdvisor) emitStat(stats map[int]monitor.DomainMonStat, metricName string) { for domId, monStat := range stats { for group, ccdMBs := range monStat { dom := fmt.Sprintf("%d", domId) @@ -71,33 +71,33 @@ func (d *domainAdvisor) emitStat(stats map[int]monitor.DomainMonStat, metricName "group": group, "ccd": fmt.Sprintf("%d", ccd), } - emitKV(d.emitter, metricName, v.TotalMB, tags) + emitKV(a.emitter, metricName, v.TotalMB, tags) } } } } -func (d *domainAdvisor) emitIncomingTargets(groupedDomIncomingTargets map[string][]int) { - emitNamedGroupTargets(d.emitter, nameMBMIncomingTarget, groupedDomIncomingTargets) +func (a *uniqPriorityAdvisor) emitIncomingTargets(groupedDomIncomingTargets map[string][]int) { + emitNamedGroupTargets(a.emitter, nameMBMIncomingTarget, groupedDomIncomingTargets) } -func (d *domainAdvisor) emitOutgoingTargets(groupedDomOutgoingTargets map[string][]int) { - emitNamedGroupTargets(d.emitter, nameMBMOutgoingTarget, groupedDomOutgoingTargets) +func (a *uniqPriorityAdvisor) emitOutgoingTargets(groupedDomOutgoingTargets map[string][]int) { + emitNamedGroupTargets(a.emitter, nameMBMOutgoingTarget, groupedDomOutgoingTargets) } -func (d *domainAdvisor) emitAdjustedOutgoingTargets(groupedDomOutgoingTargets map[string][]int) { - emitNamedGroupTargets(d.emitter, nameMBMAdjustedOutgoingTarget, groupedDomOutgoingTargets) +func (a *uniqPriorityAdvisor) emitAdjustedOutgoingTargets(groupedDomOutgoingTargets map[string][]int) { + emitNamedGroupTargets(a.emitter, nameMBMAdjustedOutgoingTarget, groupedDomOutgoingTargets) } -func (d *domainAdvisor) emitRawPlan(plan *plan.MBPlan) { - d.emitPlanWithMetricName(plan, namePlanRaw) +func (a *uniqPriorityAdvisor) emitRawPlan(plan *plan.MBPlan) { + a.emitPlanWithMetricName(plan, namePlanRaw) } -func (d *domainAdvisor) emitUpdatePlan(plan *plan.MBPlan) { - d.emitPlanWithMetricName(plan, namePlanUpdate) +func (a *uniqPriorityAdvisor) emitUpdatePlan(plan *plan.MBPlan) { + a.emitPlanWithMetricName(plan, namePlanUpdate) } -func (d *domainAdvisor) emitPlanWithMetricName(plan *plan.MBPlan, metricName string) { +func (a *uniqPriorityAdvisor) emitPlanWithMetricName(plan *plan.MBPlan, metricName string) { if plan == nil || len(plan.MBGroups) == 0 { return } @@ -108,7 +108,7 @@ func (d *domainAdvisor) emitPlanWithMetricName(plan *plan.MBPlan, metricName str "group": group, "ccd": fmt.Sprintf("%d", ccd), } - emitKV(d.emitter, metricName, v, tags) + emitKV(a.emitter, metricName, v, tags) } } } diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go b/pkg/agent/qrm-plugins/mb/advisor/priority_advisor.go similarity index 68% rename from pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go rename to pkg/agent/qrm-plugins/mb/advisor/priority_advisor.go index f658dfaab9..1df0cd940a 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator.go +++ b/pkg/agent/qrm-plugins/mb/advisor/priority_advisor.go @@ -21,15 +21,19 @@ import ( "k8s.io/apimachinery/pkg/util/sets" + "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/domain" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/monitor" "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/mb/plan" + "github.com/kubewharf/katalyst-core/pkg/metrics" ) -// priorityGroupDecorator adapts with resctrl groups of identical priority as if a logical group. +// priorityAdvisor is able to work with resctrl groups with priority; +// one groups' priority can be the same as that of others'. +// It leverages uniqPriorityAdvisor working with groups of distinct priorities only. // It targets the scenarios where the groups of same priority don't share ccd. // todo: enhance to handle multiple groups of same priority sharing ccd -type priorityGroupDecorator struct { - inner Advisor +type priorityAdvisor struct { + uniqPriorityAdvisor *uniqPriorityAdvisor } // groupInfo stores the mapping of groups and their CCDs for each domain @@ -46,19 +50,19 @@ type combinedGroupMapping map[string]ccdSet // ccdSet represents a set of CCD IDs type ccdSet = sets.Int -func (d *priorityGroupDecorator) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { - domainStats, groupInfos, err := d.combinedDomainStats(domainsMon) +func (a *priorityAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { + domainStats, groupInfos, err := a.combinedDomainStats(domainsMon) if err != nil { return nil, err } - mbPlan, err := d.inner.GetPlan(ctx, domainStats) + mbPlan, err := a.uniqPriorityAdvisor.GetPlan(ctx, domainStats) if err != nil { return nil, err } - return d.splitPlan(mbPlan, groupInfos), nil + return a.splitPlan(mbPlan, groupInfos), nil } -func (d *priorityGroupDecorator) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, *groupInfo, error) { +func (a *priorityAdvisor) combinedDomainStats(domainsMon *monitor.DomainStats) (*monitor.DomainStats, *groupInfo, error) { domainStats := &monitor.DomainStats{ Incomings: make(map[int]monitor.DomainMonStat), Outgoings: make(map[int]monitor.DomainMonStat), @@ -84,7 +88,7 @@ func (d *priorityGroupDecorator) combinedDomainStats(domainsMon *monitor.DomainS return domainStats, groupInfos, nil } -func (d *priorityGroupDecorator) splitPlan(mbPlan *plan.MBPlan, groupInfos *groupInfo) *plan.MBPlan { +func (a *priorityAdvisor) splitPlan(mbPlan *plan.MBPlan, groupInfos *groupInfo) *plan.MBPlan { for groupKey, ccdPlan := range mbPlan.MBGroups { if !isCombinedGroup(groupKey) { continue @@ -106,8 +110,15 @@ func (d *priorityGroupDecorator) splitPlan(mbPlan *plan.MBPlan, groupInfos *grou return mbPlan } -func DecorateByPriorityGroup(advisor Advisor) Advisor { - return &priorityGroupDecorator{ - inner: advisor, +func New(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, + capPercent int, XDomGroups []string, groupNeverThrottles []string, + groupCapacity map[string]int, +) Advisor { + return &priorityAdvisor{ + uniqPriorityAdvisor: newUniqPriorityAdvisor(emitter, + domains, ccdMinMB, ccdMaxMB, defaultDomainCapacity, capPercent, + XDomGroups, groupNeverThrottles, + groupCapacity, + ), } } diff --git a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go b/pkg/agent/qrm-plugins/mb/advisor/priority_advisor_test.go similarity index 99% rename from pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go rename to pkg/agent/qrm-plugins/mb/advisor/priority_advisor_test.go index e9a921d476..e4c7c79f1b 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/advisor_decorator_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/priority_advisor_test.go @@ -193,7 +193,7 @@ func Test_priorityGroupDecorator_combinedDomainStats(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - d := &priorityGroupDecorator{} + d := &priorityAdvisor{} gotStats, gotGroupInfo, err := d.combinedDomainStats(tt.domainsMon) if (err != nil) != tt.wantErr { t.Errorf("combinedDomainStats() error = %v, wantErr %v", err, tt.wantErr) @@ -267,7 +267,7 @@ func Test_priorityGroupDecorator_splitPlan(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - d := &priorityGroupDecorator{} + d := &priorityAdvisor{} got := d.splitPlan(tt.mbPlan, tt.groupInfos) if !reflect.DeepEqual(got, tt.want) { t.Errorf("splitPlan() = %v, want %v", got, tt.want) diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go b/pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor.go similarity index 67% rename from pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go rename to pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor.go index 21079d9513..9da489c177 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor.go +++ b/pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor.go @@ -36,7 +36,9 @@ import ( "github.com/kubewharf/katalyst-core/pkg/util/general" ) -type domainAdvisor struct { +// uniqPriorityAdvisor is an priorityAdvisor which can only work with resctrl groups of distinct priorities; +// due to this limitation, it should not be used directly. +type uniqPriorityAdvisor struct { emitter metrics.MetricEmitter domains domain.Domains @@ -59,123 +61,123 @@ type domainAdvisor struct { ccdDistribute distributor.Distributor } -func (d *domainAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { - d.emitStatsMtrics(domainsMon) +func (a *uniqPriorityAdvisor) GetPlan(ctx context.Context, domainsMon *monitor.DomainStats) (*plan.MBPlan, error) { + a.emitStatsMtrics(domainsMon) // identify mb incoming usage etc since the capacity applies to incoming traffic - domIncomingInfo, err := d.calcIncomingDomainStats(ctx, domainsMon) + domIncomingInfo, err := a.calcIncomingDomainStats(ctx, domainsMon) if err != nil { return nil, errors.Wrap(err, "failed to get plan") } if klog.V(6).Enabled() { domTotalMBs := getDomainTotalMBs(domIncomingInfo) - general.InfofV(6, "[mbm] [advisor] domains incoming total: %v", domTotalMBs) + general.InfofV(6, "[mbm] [priorityAdvisor] domains incoming total: %v", domTotalMBs) } - d.emitDomIncomingStatSummaryMetrics(domIncomingInfo) + a.emitDomIncomingStatSummaryMetrics(domIncomingInfo) // based on mb incoming usage info, decide incoming quotas (i.e. targets) - domIncomingQuotas := d.getIncomingDomainQuotas(ctx, domIncomingInfo) + domIncomingQuotas := a.getIncomingDomainQuotas(ctx, domIncomingInfo) groupedDomIncomingTargets := domIncomingQuotas.GetGroupedDomainSetting() if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] group-domain incoming targets: %s", + general.InfofV(6, "[mbm] [priorityAdvisor] group-domain incoming targets: %s", stringify(groupedDomIncomingTargets)) } - d.emitIncomingTargets(groupedDomIncomingTargets) + a.emitIncomingTargets(groupedDomIncomingTargets) // for each group, based on incoming targets, decide what the outgoing targets are var groupedDomOutgoingTargets map[string][]int - groupedDomOutgoingTargets, err = d.deriveOutgoingTargets(ctx, domainsMon.OutgoingGroupSumStat, groupedDomIncomingTargets) + groupedDomOutgoingTargets, err = a.deriveOutgoingTargets(ctx, domainsMon.OutgoingGroupSumStat, groupedDomIncomingTargets) if err != nil { return nil, errors.Wrap(err, "failed to get plan") } if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] group-domain outgoing targets: %s", + general.InfofV(6, "[mbm] [priorityAdvisor] group-domain outgoing targets: %s", stringify(groupedDomOutgoingTargets)) } - d.emitOutgoingTargets(groupedDomOutgoingTargets) + a.emitOutgoingTargets(groupedDomOutgoingTargets) // leverage the current observed outgoing stats (and implicit previous outgoing mb) // to adjust th outgoing mb hopeful to reach the desired target groupedDomOutgoings := domainsMon.OutgoingGroupSumStat - groupedDomainOutgoingQuotas := d.adjust(ctx, groupedDomOutgoingTargets, groupedDomOutgoings, d.capPercent) + groupedDomainOutgoingQuotas := a.adjust(ctx, groupedDomOutgoingTargets, groupedDomOutgoings, a.capPercent) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] group-domain outgoing quotas adjusted: %s", + general.InfofV(6, "[mbm] [priorityAdvisor] group-domain outgoing quotas adjusted: %s", stringify(groupedDomainOutgoingQuotas)) } - d.emitAdjustedOutgoingTargets(groupedDomainOutgoingQuotas) + a.emitAdjustedOutgoingTargets(groupedDomainOutgoingQuotas) // split outgoing mb to ccd level - groupedCCDOutgoingQuotas := d.distributeToCCDs(ctx, groupedDomainOutgoingQuotas, domainsMon.Outgoings) + groupedCCDOutgoingQuotas := a.distributeToCCDs(ctx, groupedDomainOutgoingQuotas, domainsMon.Outgoings) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] group-ccd outgoing quotas: %v", groupedCCDOutgoingQuotas) + general.InfofV(6, "[mbm] [priorityAdvisor] group-ccd outgoing quotas: %v", groupedCCDOutgoingQuotas) } rawPlan := convertToPlan(groupedCCDOutgoingQuotas) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] raw plan: %s", rawPlan) + general.InfofV(6, "[mbm] [priorityAdvisor] raw plan: %s", rawPlan) } - d.emitRawPlan(rawPlan) + a.emitRawPlan(rawPlan) // finalize plan with never-throttle groups and ccb mb checks - checkedPlan := applyPlanCCDBoundsChecks(rawPlan, d.ccdMinMB, d.ccdMaxMB) - updatePlan := maskPlanWithNoThrottles(checkedPlan, d.groupNeverThrottles, d.getNoThrottleMB()) + checkedPlan := applyPlanCCDBoundsChecks(rawPlan, a.ccdMinMB, a.ccdMaxMB) + updatePlan := maskPlanWithNoThrottles(checkedPlan, a.groupNeverThrottles, a.getNoThrottleMB()) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] mb plan update: %s", updatePlan) + general.InfofV(6, "[mbm] [priorityAdvisor] mb plan update: %s", updatePlan) } - d.emitUpdatePlan(updatePlan) + a.emitUpdatePlan(updatePlan) return updatePlan, nil } -func (d *domainAdvisor) getNoThrottleMB() int { - if d.ccdMaxMB > 0 { - return d.ccdMaxMB +func (a *uniqPriorityAdvisor) getNoThrottleMB() int { + if a.ccdMaxMB > 0 { + return a.ccdMaxMB } - return d.defaultDomainCapacity + return a.defaultDomainCapacity } -func (d *domainAdvisor) adjust(_ context.Context, +func (a *uniqPriorityAdvisor) adjust(_ context.Context, groupedSettings map[string][]int, observed map[string][]monitor.MBInfo, capPercent int, ) map[string][]int { result := map[string][]int{} activeGroups := sets.String{} for group, values := range groupedSettings { currents := getGroupOutgoingTotals(group, observed) - if _, ok := d.adjusters[group]; !ok { - d.adjusters[group] = adjuster.New(capPercent) + if _, ok := a.adjusters[group]; !ok { + a.adjusters[group] = adjuster.New(capPercent) } - result[group] = d.adjusters[group].AdjustOutgoingTargets(values, currents) + result[group] = a.adjusters[group].AdjustOutgoingTargets(values, currents) activeGroups.Insert(group) } // clean up to avoid memory leak if len(groupedSettings) > 0 { - for group := range d.adjusters { + for group := range a.adjusters { if activeGroups.Has(group) { continue } - delete(d.adjusters, group) + delete(a.adjusters, group) } } return result } -func (d *domainAdvisor) getIncomingDomainQuotas(_ context.Context, domIncomingInfo map[int]*resource.MBGroupIncomingStat, +func (a *uniqPriorityAdvisor) getIncomingDomainQuotas(_ context.Context, domIncomingInfo map[int]*resource.MBGroupIncomingStat, ) resource.DomQuotas { domQuotas := map[int]resource.GroupSettings{} for dom, incomingInfo := range domIncomingInfo { - domQuotas[dom] = d.quotaStrategy.GetGroupQuotas(incomingInfo) + domQuotas[dom] = a.quotaStrategy.GetGroupQuotas(incomingInfo) } return domQuotas } -func (d *domainAdvisor) calcIncomingDomainStats(ctx context.Context, mon *monitor.DomainStats, +func (a *uniqPriorityAdvisor) calcIncomingDomainStats(ctx context.Context, mon *monitor.DomainStats, ) (map[int]*resource.MBGroupIncomingStat, error) { incomingInfoOfDomains := make(map[int]*resource.MBGroupIncomingStat) var err error for domID, incomingStats := range mon.Incomings { - incomingInfoOfDomains[domID], err = d.calcIncomingStat(domID, incomingStats) + incomingInfoOfDomains[domID], err = a.calcIncomingStat(domID, incomingStats) if err != nil { return nil, errors.Wrap(err, "failed to calc domain quotas") } @@ -183,8 +185,8 @@ func (d *domainAdvisor) calcIncomingDomainStats(ctx context.Context, mon *monito return incomingInfoOfDomains, nil } -func (d *domainAdvisor) calcIncomingStat(domID int, incomingStats monitor.GroupMBStats) (*resource.MBGroupIncomingStat, error) { - capacity, err := d.getEffectiveCapacity(domID, incomingStats) +func (a *uniqPriorityAdvisor) calcIncomingStat(domID int, incomingStats monitor.GroupMBStats) (*resource.MBGroupIncomingStat, error) { + capacity, err := a.getEffectiveCapacity(domID, incomingStats) if err != nil { return nil, errors.Wrap(err, "failed to calc domain capacity") } @@ -194,15 +196,15 @@ func (d *domainAdvisor) calcIncomingStat(domID int, incomingStats monitor.GroupM } // getEffectiveCapacity gets the effective memory bandwidth capacity of specified domain, with its given resource usage -func (d *domainAdvisor) getEffectiveCapacity(domID int, domIncomingStats monitor.GroupMBStats) (int, error) { - if _, ok := d.domains[domID]; !ok { +func (a *uniqPriorityAdvisor) getEffectiveCapacity(domID int, domIncomingStats monitor.GroupMBStats) (int, error) { + if _, ok := a.domains[domID]; !ok { return 0, fmt.Errorf("unknown domain %d", domID) } - return getMinEffectiveCapacity(d.defaultDomainCapacity, d.groupCapacityInMB, domIncomingStats), nil + return getMinEffectiveCapacity(a.defaultDomainCapacity, a.groupCapacityInMB, domIncomingStats), nil } -func (d *domainAdvisor) deriveOutgoingTargets(_ context.Context, +func (a *uniqPriorityAdvisor) deriveOutgoingTargets(_ context.Context, outgoingGroupSumStat map[string][]monitor.MBInfo, incomingTargets map[string][]int, ) (map[string][]int, error) { // for each group: based on incoming targets, decide what the outgoing targets are @@ -215,17 +217,17 @@ func (d *domainAdvisor) deriveOutgoingTargets(_ context.Context, continue } - if d.xDomGroups.Has(group) { + if a.xDomGroups.Has(group) { localRatio := make([]float64, len(domSums)) for i, domSum := range domSums { // limit the excessive remote traffic if applicable - remoteTarget := d.domains[i].GetAlienMBLimit() + remoteTarget := a.domains[i].GetAlienMBLimit() if remoteTarget > domSum.RemoteMB { remoteTarget = domSum.RemoteMB } localRatio[i] = float64(domSum.LocalMB) / float64(domSum.LocalMB+remoteTarget) } - outgoingTargets, err := d.flower.InvertFlow(localRatio, groupIncomingTargets) + outgoingTargets, err := a.flower.InvertFlow(localRatio, groupIncomingTargets) if err != nil { return nil, errors.Wrap(err, "failed to get sourcing outgoing out of desired incoming targets") } @@ -239,14 +241,14 @@ func (d *domainAdvisor) deriveOutgoingTargets(_ context.Context, return result, nil } -func (d *domainAdvisor) distributeToCCDs(_ context.Context, +func (a *uniqPriorityAdvisor) distributeToCCDs(_ context.Context, quotas map[string][]int, outgoingStat map[int]monitor.GroupMBStats, ) map[string]map[int]int { result := map[string]map[int]int{} for group, domQuota := range quotas { // each domain is treated independently for domID, domTotal := range domQuota { - ccdDistributions := d.domainDistributeGroup(domID, group, domTotal, outgoingStat) + ccdDistributions := a.domainDistributeGroup(domID, group, domTotal, outgoingStat) if len(ccdDistributions) == 0 { continue } @@ -262,7 +264,7 @@ func (d *domainAdvisor) distributeToCCDs(_ context.Context, return result } -func (d *domainAdvisor) domainDistributeGroup(domID int, group string, +func (a *uniqPriorityAdvisor) domainDistributeGroup(domID int, group string, domTotal int, outgoingStat map[int]monitor.GroupMBStats, ) map[int]int { weights := map[int]int{} @@ -270,9 +272,9 @@ func (d *domainAdvisor) domainDistributeGroup(domID int, group string, for ccd, stat := range groupStat { weights[ccd] = stat.TotalMB } - domCCDQuotas := d.ccdDistribute.Distribute(domTotal, weights) + domCCDQuotas := a.ccdDistribute.Distribute(domTotal, weights) if klog.V(6).Enabled() { - general.InfofV(6, "[mbm] [advisor] domain %d, group %s, total %v, weights %v, distribute to ccd quotas: %v", + general.InfofV(6, "[mbm] [priorityAdvisor] domain %d, group %s, total %v, weights %v, distribute to ccd quotas: %v", domID, group, domTotal, weights, domCCDQuotas) } result := map[int]int{} @@ -282,15 +284,15 @@ func (d *domainAdvisor) domainDistributeGroup(domID int, group string, return result } -func NewDomainAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, +func newUniqPriorityAdvisor(emitter metrics.MetricEmitter, domains domain.Domains, ccdMinMB, ccdMaxMB int, defaultDomainCapacity int, capPercent int, XDomGroups []string, groupNeverThrottles []string, groupCapacity map[string]int, -) Advisor { +) *uniqPriorityAdvisor { // do not throttle built-in "/" anytime notThrottles := sets.NewString("/") notThrottles.Insert(groupNeverThrottles...) - return &domainAdvisor{ + return &uniqPriorityAdvisor{ emitter: emitter, domains: domains, xDomGroups: sets.NewString(XDomGroups...), diff --git a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go b/pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor_test.go similarity index 99% rename from pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go rename to pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor_test.go index 6362a4214c..a2e421f9c6 100644 --- a/pkg/agent/qrm-plugins/mb/advisor/domain_advisor_test.go +++ b/pkg/agent/qrm-plugins/mb/advisor/uniq_priority_advisor_test.go @@ -92,7 +92,7 @@ func Test_domainAdvisor_getEffectiveCapacity(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - d := &domainAdvisor{ + d := &uniqPriorityAdvisor{ domains: tt.fields.domains, xDomGroups: tt.fields.xDomGroups, groupCapacityInMB: tt.fields.groupCapacityInMB, @@ -226,7 +226,7 @@ func Test_domainAdvisor_calcIncomingQuotas(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - d := &domainAdvisor{ + d := &uniqPriorityAdvisor{ domains: tt.fields.domains, xDomGroups: tt.fields.XDomGroups, groupCapacityInMB: tt.fields.GroupCapacityInMB, @@ -515,7 +515,7 @@ func Test_domainAdvisor_GetPlan(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - d := &domainAdvisor{ + d := &uniqPriorityAdvisor{ domains: tt.fields.domains, defaultDomainCapacity: tt.fields.defaultDomainCapacity, capPercent: 100, diff --git a/pkg/agent/qrm-plugins/mb/policy/plugin.go b/pkg/agent/qrm-plugins/mb/policy/plugin.go index 9927cd0689..15e241cadb 100644 --- a/pkg/agent/qrm-plugins/mb/policy/plugin.go +++ b/pkg/agent/qrm-plugins/mb/policy/plugin.go @@ -127,16 +127,12 @@ func (m *MBPlugin) Start() (err error) { } // initializing advisor field is deferred as qos group mb capacities is known now - general.Infof("mbm: create traditional advior") - m.advisor = advisor.NewDomainAdvisor(m.emitter, m.domains, + general.Infof("mbm: create advior able to treat multiple resctrl groups with identical priority") + m.advisor = advisor.New(m.emitter, m.domains, m.conf.MinCCDMB, m.conf.MaxCCDMB, defaultMBDomainCapacity, m.conf.MBCapLimitPercent, m.conf.CrossDomainGroups, m.conf.MBQRMPluginConfig.NoThrottleGroups, groupCapacities) - if !m.conf.GroupPriorityUnique { - general.Infof("mbm: use enhanced advior able to treat multiple resctrl groups with identical priority") - m.advisor = advisor.DecorateByPriorityGroup(m.advisor) - } go func() { wait.Until(m.run, interval, m.chStop) diff --git a/pkg/config/agent/qrm/mb_plugin.go b/pkg/config/agent/qrm/mb_plugin.go index 73206e78a9..9df6de6f07 100644 --- a/pkg/config/agent/qrm/mb_plugin.go +++ b/pkg/config/agent/qrm/mb_plugin.go @@ -38,7 +38,6 @@ type MBQRMPluginConfig struct { ResetResctrlOnly bool LocalIsVictimAndTotalIsAllRead bool - GroupPriorityUnique bool ExtraGroupPriorities map[string]int }