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 "fmt" 26 "math" 27 "strings" 28 "testing" 29 30 "android/soong/android" 31) 32 33const ( 34 performance_test_dir = "." 35) 36 37func genCustomModule(i int, convert bool) string { 38 var conversionString string 39 if convert { 40 conversionString = `bazel_module: { bp2build_available: true },` 41 } 42 return fmt.Sprintf(` 43custom { 44 name: "arch_paths_%[1]d", 45 string_list_prop: ["\t", "\n"], 46 string_prop: "a\t\n\r", 47 arch_paths: ["outer", ":outer_dep_%[1]d"], 48 arch: { 49 x86: { 50 arch_paths: ["abc", ":x86_dep_%[1]d"], 51 }, 52 x86_64: { 53 arch_paths: ["64bit"], 54 arch_paths_exclude: ["outer"], 55 }, 56 }, 57 %[2]s 58} 59 60custom { 61 name: "outer_dep_%[1]d", 62 %[2]s 63} 64 65custom { 66 name: "x86_dep_%[1]d", 67 %[2]s 68} 69`, i, conversionString) 70} 71 72func genCustomModuleBp(pctConverted float64) string { 73 modules := 100 74 75 bp := make([]string, 0, modules) 76 toConvert := int(math.Round(float64(modules) * pctConverted)) 77 78 for i := 0; i < modules; i++ { 79 bp = append(bp, genCustomModule(i, i < toConvert)) 80 } 81 return strings.Join(bp, "\n\n") 82} 83 84type testConfig struct { 85 config android.Config 86 ctx *android.TestContext 87 codegenCtx *CodegenContext 88} 89 90func (tc testConfig) parse() []error { 91 _, errs := tc.ctx.ParseFileList(performance_test_dir, []string{"Android.bp"}) 92 return errs 93} 94 95func (tc testConfig) resolveDependencies() []error { 96 _, errs := tc.ctx.ResolveDependencies(tc.config) 97 return errs 98} 99 100func (tc testConfig) convert() { 101 generateBazelTargetsForDir(tc.codegenCtx, performance_test_dir) 102} 103 104func setup(builddir string, tcSize float64) testConfig { 105 config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil) 106 ctx := android.NewTestContext(config) 107 108 registerCustomModuleForBp2buildConversion(ctx) 109 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "") 110 return testConfig{ 111 config, 112 ctx, 113 codegenCtx, 114 } 115} 116 117var pctToConvert = []float64{0.0, 0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 1.0} 118 119// This is not intended to test performance, but to verify performance infra continues to work 120func TestConvertManyModulesFull(t *testing.T) { 121 for _, tcSize := range pctToConvert { 122 123 t.Run(fmt.Sprintf("pctConverted %f", tcSize), func(t *testing.T) { 124 testConfig := setup(buildDir, tcSize) 125 126 errs := testConfig.parse() 127 if len(errs) > 0 { 128 t.Fatalf("Unexpected errors: %s", errs) 129 } 130 131 errs = testConfig.resolveDependencies() 132 if len(errs) > 0 { 133 t.Fatalf("Unexpected errors: %s", errs) 134 } 135 136 testConfig.convert() 137 }) 138 } 139} 140 141func BenchmarkManyModulesFull(b *testing.B) { 142 for _, tcSize := range pctToConvert { 143 144 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 145 for n := 0; n < b.N; n++ { 146 b.StopTimer() 147 testConfig := setup(buildDir, tcSize) 148 149 b.StartTimer() 150 errs := testConfig.parse() 151 if len(errs) > 0 { 152 b.Fatalf("Unexpected errors: %s", errs) 153 } 154 155 errs = testConfig.resolveDependencies() 156 if len(errs) > 0 { 157 b.Fatalf("Unexpected errors: %s", errs) 158 } 159 160 testConfig.convert() 161 b.StopTimer() 162 } 163 }) 164 } 165} 166 167func BenchmarkManyModulesResolveDependencies(b *testing.B) { 168 for _, tcSize := range pctToConvert { 169 170 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 171 for n := 0; n < b.N; n++ { 172 b.StopTimer() 173 // setup we don't want to measure 174 testConfig := setup(buildDir, tcSize) 175 176 errs := testConfig.parse() 177 if len(errs) > 0 { 178 b.Fatalf("Unexpected errors: %s", errs) 179 } 180 181 b.StartTimer() 182 errs = testConfig.resolveDependencies() 183 b.StopTimer() 184 if len(errs) > 0 { 185 b.Fatalf("Unexpected errors: %s", errs) 186 } 187 188 testConfig.convert() 189 } 190 }) 191 } 192} 193 194func BenchmarkManyModulesGenerateBazelTargetsForDir(b *testing.B) { 195 for _, tcSize := range pctToConvert { 196 197 b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) { 198 for n := 0; n < b.N; n++ { 199 b.StopTimer() 200 // setup we don't want to measure 201 testConfig := setup(buildDir, tcSize) 202 203 errs := testConfig.parse() 204 if len(errs) > 0 { 205 b.Fatalf("Unexpected errors: %s", errs) 206 } 207 208 errs = testConfig.resolveDependencies() 209 if len(errs) > 0 { 210 b.Fatalf("Unexpected errors: %s", errs) 211 } 212 213 b.StartTimer() 214 testConfig.convert() 215 b.StopTimer() 216 } 217 }) 218 } 219} 220