Skip to content

Commit

Permalink
using required number of cores for picking best recommendation
Browse files Browse the repository at this point in the history
  • Loading branch information
shaharuk-yb committed Feb 26, 2025
1 parent aab9b6e commit c805269
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
16 changes: 9 additions & 7 deletions yb-voyager/src/migassessment/sizing.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ type IntermediateRecommendation struct {
EstimatedTimeInMinForImport float64
ParallelVoyagerJobs float64
FailureReasoning string
CoresNeeded float64
}

const (
Expand Down Expand Up @@ -301,13 +302,11 @@ func pickBestRecommendation(recommendation map[int]IntermediateRecommendation) I
if rec.FailureReasoning == "" {
foundRecommendation = true
// Update finalRecommendation if the current recommendation has fewer cores.
// Buffer to choose setup with higher vCPU if difference between required cores between two setup is less
// than higher vCPU count.
if minCores > int(rec.NumNodes)*rec.VCPUsPerInstance &&
(minCores-int(rec.NumNodes)*rec.VCPUsPerInstance) > finalRecommendation.VCPUsPerInstance {
log.Infof(fmt.Sprintf("vCPU: %v & cores required: %v gives nodes required: %v\n", rec.VCPUsPerInstance, rec.CoresNeeded, rec.NumNodes))
if minCores > int(rec.CoresNeeded) {
finalRecommendation = rec
minCores = int(rec.NumNodes) * rec.VCPUsPerInstance
} else if minCores == int(rec.NumNodes)*rec.VCPUsPerInstance {
minCores = int(rec.CoresNeeded)
} else if minCores == int(rec.CoresNeeded) {
// If the number of cores is the same across machines, recommend the machine with higher core count
if rec.VCPUsPerInstance > finalRecommendation.VCPUsPerInstance {
finalRecommendation = rec
Expand Down Expand Up @@ -383,6 +382,7 @@ func findNumNodesNeededBasedOnThroughputRequirement(sourceIndexMetadata []Source
ShardedSize: previousRecommendation.ShardedSize,
EstimatedTimeInMinForImport: previousRecommendation.EstimatedTimeInMinForImport,
FailureReasoning: previousRecommendation.FailureReasoning,
CoresNeeded: neededCores,
}
}
// Return updated recommendation map
Expand Down Expand Up @@ -431,7 +431,9 @@ func findNumNodesNeededBasedOnTabletsRequired(sourceIndexMetadata []SourceDBMeta
// update recommendation to use the maximum of the existing recommended nodes and nodes calculated based on tablets
// Caveat: if new nodes required is more than the existing recommended nodes, we would need to
// re-evaluate tablets required. Although, in this iteration we've skipping re-evaluation.
rec.NumNodes = math.Max(rec.NumNodes, nodesRequired)
currentMaxRequiredNodes := math.Max(nodesRequired, rec.NumNodes)
rec.CoresNeeded = lo.Ternary(nodesRequired <= rec.NumNodes, rec.CoresNeeded, currentMaxRequiredNodes*float64(rec.VCPUsPerInstance))
rec.NumNodes = currentMaxRequiredNodes
recommendation[i] = rec
}
}
Expand Down
61 changes: 58 additions & 3 deletions yb-voyager/src/migassessment/sizing_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:build unit

/*
Copyright (c) YugabyteDB, Inc.
Expand Down Expand Up @@ -777,6 +775,7 @@ func TestFindNumNodesNeededBasedOnTabletsRequired_CanSupportTablets(t *testing.T
},
VCPUsPerInstance: 4,
NumNodes: 3,
CoresNeeded: 10,
},
}

Expand All @@ -786,6 +785,7 @@ func TestFindNumNodesNeededBasedOnTabletsRequired_CanSupportTablets(t *testing.T

// check if the num nodes in updated recommendation is same as before(3) meaning no scaling is required
assert.Equal(t, float64(3), updatedRecommendation[4].NumNodes)
assert.Equal(t, float64(10), updatedRecommendation[4].CoresNeeded)
}

// validate that the tablets cannot be supported by existing nodes and scaling is needed
Expand Down Expand Up @@ -816,15 +816,17 @@ func TestFindNumNodesNeededBasedOnTabletsRequired_NeedMoreNodes(t *testing.T) {
},
VCPUsPerInstance: 4,
NumNodes: 3,
CoresNeeded: 10,
},
}

// Run the function
updatedRecommendation :=
findNumNodesNeededBasedOnTabletsRequired(sourceIndexMetadata, shardedLimits, recommendation)

// check if the num nodes in updated recommendation has increased. Meaning scaling is required.
// check if the num nodes and cores in updated recommendation has increased. Meaning scaling is required.
assert.Equal(t, float64(6), updatedRecommendation[4].NumNodes)
assert.Equal(t, float64(24), updatedRecommendation[4].CoresNeeded)
}

/*
Expand All @@ -836,11 +838,13 @@ func TestPickBestRecommendation_PickOneWithOptimalNodesAndCores(t *testing.T) {
4: {
VCPUsPerInstance: 4,
NumNodes: 10,
CoresNeeded: 40,
FailureReasoning: "",
},
8: {
VCPUsPerInstance: 8,
NumNodes: 3,
CoresNeeded: 24,
FailureReasoning: "",
},
}
Expand All @@ -855,16 +859,19 @@ func TestPickBestRecommendation_PickOneWithOptimalNodesAndCoresWhenSomeHasFailur
4: {
VCPUsPerInstance: 4,
NumNodes: 10,
CoresNeeded: 40,
FailureReasoning: "has some failure",
},
8: {
VCPUsPerInstance: 8,
NumNodes: 3,
CoresNeeded: 24,
FailureReasoning: "has some failure as well",
},
16: {
VCPUsPerInstance: 16,
NumNodes: 3,
CoresNeeded: 48,
FailureReasoning: "",
},
}
Expand Down Expand Up @@ -897,6 +904,54 @@ func TestPickBestRecommendation_PickLastMaxCoreRecommendationWhenNoneCanSupport(
assert.Equal(t, 16, bestPick.VCPUsPerInstance)
}

// validate if the recommendation with min required cores is used.
func TestPickBestRecommendation_PickRecommendationWithMinCoresRequired(t *testing.T) {
recommendations := map[int]IntermediateRecommendation{
4: {
VCPUsPerInstance: 4,
NumNodes: 83,
CoresNeeded: 329,
},
8: {
VCPUsPerInstance: 8,
NumNodes: 37,
CoresNeeded: 296,
},
16: {
VCPUsPerInstance: 16,
NumNodes: 19,
CoresNeeded: 290,
},
}
bestPick := pickBestRecommendation(recommendations)
// validate the best recommendation which is 16 vcpus per instance is picked up
assert.Equal(t, 16, bestPick.VCPUsPerInstance)
}

// validate if the recommendation with higher vCPU is selected if required cores are same.
func TestPickBestRecommendation_PickHigherVCPURecommendationWhenSameCoresRequired(t *testing.T) {
recommendations := map[int]IntermediateRecommendation{
4: {
VCPUsPerInstance: 4,
NumNodes: 12,
CoresNeeded: 48,
},
8: {
VCPUsPerInstance: 8,
NumNodes: 6,
CoresNeeded: 48,
},
16: {
VCPUsPerInstance: 16,
NumNodes: 3,
CoresNeeded: 48,
},
}
bestPick := pickBestRecommendation(recommendations)
// validate the best recommendation which is 16 vcpus per instance is picked up
assert.Equal(t, 16, bestPick.VCPUsPerInstance)
}

/*
===== Test functions to test calculateTimeTakenAndParallelJobsForImport function =====
*/
Expand Down

0 comments on commit c805269

Please sign in to comment.