• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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