benchmarks/benchmark/tools/model-load-benchmark/suite-generator/generator.go (184 lines of code) (raw):

package suitegenerator import ( "fmt" "reflect" "tool/config" ) var RequestLimitMap = map[string]string{ "CPURequest": "CPULimit", "MemoryRequest": "MemoryLimit", "EphemeralStorageRequest": "EphemeralStorageLimit", } type Suite struct { BaseCase config.Config Cases []config.Config } // GenerateCases creates test cases func GenerateCases(base config.Config) *Suite { suite := Suite{BaseCase: deepCopyConfig(base)} suite.Cases = generateSideCarAndVolumeCases(base) return &suite } func generateSideCarAndVolumeCases(base config.Config) []config.Config { sideCarCases := []config.Config{deepCopyConfig(base)} if base.SideCarResources != nil { sideCarCases = generateResourceCasesForStruct(base, "SideCarResources", reflect.ValueOf(base.SideCarResources)) } fmt.Printf("Number of sidecarresource combinations generated %v \n", len(sideCarCases)) var volumeCases []config.Config for _, sideCarCase := range sideCarCases { if sideCarCase.VolumeAttributes != nil { generatedVolumeCases := generateResourceCasesForStruct(sideCarCase, "VolumeAttributes", reflect.ValueOf(sideCarCase.VolumeAttributes)) volumeCases = append(volumeCases, generatedVolumeCases...) } else { volumeCases = append(volumeCases, sideCarCase) } } fmt.Printf("Number of sidecarresource and volume case combinations generated %v\n", len(volumeCases)) var finalCases []config.Config for _, volumeCase := range volumeCases { if volumeCase.VolumeAttributes != nil { generatedBoolCases := generateBoolCasesForStruct(volumeCase) finalCases = append(finalCases, generatedBoolCases...) } else { finalCases = append(finalCases, volumeCase) } } fmt.Printf("Number of all combinations generated %v \n", len(finalCases)) if len(finalCases) == 0 { finalCases = append(finalCases, deepCopyConfig(base)) } return finalCases } func generateBoolCasesForStruct(base config.Config) []config.Config { var cases []config.Config combinations := []struct { EnableParallelDownloads bool FileCacheForRangeRead bool }{ {true, true}, {true, false}, {false, true}, {false, false}, } for _, combo := range combinations { newCase := deepCopyConfig(base) if newCase.VolumeAttributes != nil { newCase.VolumeAttributes.MountOptions.FileCache.EnableParallelDownloads = combo.EnableParallelDownloads if !combo.EnableParallelDownloads { newCase.VolumeAttributes.MountOptions.FileCache.ParallelDownloadsPerFile.Base = 0 newCase.VolumeAttributes.MountOptions.FileCache.MaxParallelDownloads.Base = 0 } } if newCase.VolumeAttributes != nil { newCase.VolumeAttributes.FileCacheForRangeRead = combo.FileCacheForRangeRead } cases = append(cases, newCase) } return cases } func generateResourceCasesForStruct(base config.Config, structName string, structVal reflect.Value) []config.Config { var cases []config.Config for i := 0; i < structVal.Elem().NumField(); i++ { field := structVal.Elem().Field(i) fieldType := structVal.Elem().Type().Field(i) if field.Type() == reflect.TypeOf(config.Resource{}) { resource := field.Interface().(config.Resource) if resource.Step > 0 && resource.Max > resource.Base { // Check if the field is a request that has a limit limitFieldName, isRequest := RequestLimitMap[fieldType.Name] limitField := structVal.Elem().FieldByName(limitFieldName) limitExceeded := false var limitResource config.Resource var normalizedLimit int if limitField.IsValid() { limitResource = limitField.Interface().(config.Resource) var e error normalizedLimit, e = normalizeToBaseUnit(limitResource.Base, limitResource.Unit) if e != nil { fmt.Printf("Error normalizing limit: %v\n", e) continue } } // request should be less than limit if isRequest { if limitField.IsValid() { // Normalize both resources to the same unit for comparison normalizedRequest, err := normalizeToBaseUnit(resource.Base, resource.Unit) if err != nil { fmt.Printf("Error normalizing request: %v\n", err) continue } // Compare the normalized values if normalizedRequest > normalizedLimit { limitExceeded = true } } } // Create cases if limits aren't exceeded if !limitExceeded { for val := resource.Base; val <= resource.Max; val += resource.Step { if val > resource.Max { break } newCase := deepCopyConfig(base) updatedResource := config.Resource{Base: val, Unit: resource.Unit, Step: resource.Step, Max: resource.Max} // request should be less than limit if isRequest { if limitField.IsValid() { // Normalize both resources to the same unit for comparison normalizedRequest, err := normalizeToBaseUnit(updatedResource.Base, updatedResource.Unit) if err != nil { fmt.Printf("Error normalizing request: %v\n", err) continue } // Compare the normalized values if normalizedRequest > normalizedLimit { continue } } } if structName == "SideCarResources" { newCase.SideCarResources = setNestedResourceField(newCase.SideCarResources, fieldType.Name, updatedResource).(*config.SideCarResources) } else if structName == "VolumeAttributes" { newCase.VolumeAttributes = setNestedResourceField(newCase.VolumeAttributes, fieldType.Name, updatedResource).(*config.VolumeAttributes) } cases = append(cases, newCase) } } } } } return cases } func deepCopyConfig(base config.Config) config.Config { copy := base if base.SideCarResources != nil { sideCarCopy := *base.SideCarResources copy.SideCarResources = &sideCarCopy } if base.VolumeAttributes != nil { volumeCopy := *base.VolumeAttributes copy.VolumeAttributes = &volumeCopy if base.VolumeAttributes.MountOptions.FileCache != (config.FileCache{}) { fileCacheCopy := base.VolumeAttributes.MountOptions.FileCache copy.VolumeAttributes.MountOptions.FileCache = fileCacheCopy } } return copy } func normalizeToBaseUnit(value int, unit string) (int, error) { switch unit { case "Mi": return value * 1_024, nil case "Gi": return value * 1_024 * 1_024, nil case "Ti": return value * 1_024 * 1_024 * 1_024, nil case "": return value * 1_000, nil // Convert cores to milli-cores case "m": return value, nil default: return value, nil } } func setNestedResourceField(nested interface{}, fieldName string, value config.Resource) interface{} { v := reflect.ValueOf(nested).Elem() field := v.FieldByName(fieldName) if field.IsValid() && field.CanSet() { field.Set(reflect.ValueOf(value)) } return v.Addr().Interface() }