1// Copyright 2021 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package bp2build 16 17// to run the benchmarks in this file, you must run go test with the -bench. 18// The benchmarked portion will run for the specified time (can be set via -benchtime) 19// This can mean if you are benchmarking a faster portion of a larger operation, it will take 20// longer. 21// If you are seeing a small number of iterations for a specific run, the data is less reliable, to 22// run for longer, set -benchtime to a larger value. 23 24import ( 25 "android/soong/android" 26 "fmt" 27 "math" 28 "strings" 29 "testing" 30) 31 32const ( 33 performance_test_dir = "." 34) 35 36func genCustomModule(i int, convert bool) string { 37 var conversionString string 38 if convert { 39 conversionString = `bazel_module: { bp2build_available: true },` 40 } 41 return fmt.Sprintf(` 42custom { 43 name: "arch_paths_%[1]d", 44 string_list_prop: ["\t", "\n"], 45 string_prop: "a\t\n\r", 46 arch_paths: ["outer", ":outer_dep_%[1]d"], 47 arch: { 48 x86: { 49 arch_paths: ["abc", ":x86_dep_%[1]d"], 50 }, 51 x86_64: { 52 arch_paths: ["64bit"], 53 arch_paths_exclude: ["outer"], 54 }, 55 }, 56 %[2]s 57} 58 59custom { 60 name: "outer_dep_%[1]d", 61 %[2]s 62} 63 64custom { 65 name: "x86_dep_%[1]d", 66 %[2]s 67} 68`, i, conversionString) 69} 70 71func genCustomModuleBp(pctConverted float64) string { 72 modules := 100 73 74 bp := make([]string, 0, modules) 75 toConvert := int(math.Round(float64(modules) * pctConverted)) 76 77 for i := 0; i < modules; i++ { 78 bp = append(bp, genCustomModule(i, i < toConvert)) 79 } 80 return strings.Join(bp, "\n\n") 81} 82 83type testConfig struct { 84 config android.Config 85 ctx *android.TestContext 86 codegenCtx *CodegenContext 87} 88 89func (tc testConfig) parse() []error { 90 _, errs := tc.ctx.ParseFileList(performance_test_dir, []string{"Android.bp"}) 91 return errs 92} 93 94func (tc testConfig) resolveDependencies() []error { 95 _, errs := tc.ctx.ResolveDependencies(tc.config) 96 return errs 97} 98 99func (tc testConfig) convert() { 100 generateBazelTargetsForDir(tc.codegenCtx, performance_test_dir) 101} 102 103func setup(builddir string, tcSize float64) testConfig { 104 config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil) 105 ctx := android.NewTestContext(config) 106 107 registerCustomModuleForBp2buildConversion(ctx) 108 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) 109 return testConfig{ 110 config, 111 ctx, 112 codegenCtx, 113 } 114} 115 116var pctToConvert = []float64{0.0, 0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 1.0} 117 118// This is not intended to test performance, but to verify performance infra continues to work 119func TestConvertManyModulesFull(t *testing.T) { 120 for _, tcSize := range pctToConvert { 121 122 t.Run(fmt.Sprintf("pctConverted %f", tcSize), func(t *testing.T) { 123 testConfig := setup(buildDir, tcSize) 124 125 errs := testConfig.parse() 126 if len(errs) > 0 { 127 t.Fatalf("Unexpected errors: %s", errs) 128 } 129 130 errs = testConfig.resolveDependencies() 131 if len(errs) > 0 { 132 t.Fatalf("Unexpected errors: %s", errs) 133 } 134 135 testConfig.convert() 136 }) 137 } 138} 139 140func BenchmarkManyModulesFull(b *testing.B) { 141 for _, tcSize := range pctToConvert { 142 143 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 144 for n := 0; n < b.N; n++ { 145 b.StopTimer() 146 testConfig := setup(buildDir, tcSize) 147 148 b.StartTimer() 149 errs := testConfig.parse() 150 if len(errs) > 0 { 151 b.Fatalf("Unexpected errors: %s", errs) 152 } 153 154 errs = testConfig.resolveDependencies() 155 if len(errs) > 0 { 156 b.Fatalf("Unexpected errors: %s", errs) 157 } 158 159 testConfig.convert() 160 b.StopTimer() 161 } 162 }) 163 } 164} 165 166func BenchmarkManyModulesResolveDependencies(b *testing.B) { 167 for _, tcSize := range pctToConvert { 168 169 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 170 for n := 0; n < b.N; n++ { 171 b.StopTimer() 172 // setup we don't want to measure 173 testConfig := setup(buildDir, tcSize) 174 175 errs := testConfig.parse() 176 if len(errs) > 0 { 177 b.Fatalf("Unexpected errors: %s", errs) 178 } 179 180 b.StartTimer() 181 errs = testConfig.resolveDependencies() 182 b.StopTimer() 183 if len(errs) > 0 { 184 b.Fatalf("Unexpected errors: %s", errs) 185 } 186 187 testConfig.convert() 188 } 189 }) 190 } 191} 192 193func BenchmarkManyModulesGenerateBazelTargetsForDir(b *testing.B) { 194 for _, tcSize := range pctToConvert { 195 196 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 197 for n := 0; n < b.N; n++ { 198 b.StopTimer() 199 // setup we don't want to measure 200 testConfig := setup(buildDir, tcSize) 201 202 errs := testConfig.parse() 203 if len(errs) > 0 { 204 b.Fatalf("Unexpected errors: %s", errs) 205 } 206 207 errs = testConfig.resolveDependencies() 208 if len(errs) > 0 { 209 b.Fatalf("Unexpected errors: %s", errs) 210 } 211 212 b.StartTimer() 213 testConfig.convert() 214 b.StopTimer() 215 } 216 }) 217 } 218} 219