• 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	"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