@@ -2,24 +2,38 @@ package com.squareup.francis
22
33import androidx.benchmark.ExperimentalBenchmarkConfigApi
44import androidx.benchmark.ExperimentalConfig
5+ import androidx.benchmark.macro.ExperimentalMetricApi
6+ import androidx.benchmark.macro.Metric.Measurement
7+ import androidx.benchmark.macro.TraceMetric
58import androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi
9+ import androidx.benchmark.perfetto.PerfettoConfig
610import androidx.benchmark.macro.CompilationMode
711import androidx.benchmark.macro.MacrobenchmarkScope
812import androidx.benchmark.macro.Metric
913import androidx.benchmark.macro.StartupMode
1014import androidx.benchmark.macro.junit4.MacrobenchmarkRule
15+ import androidx.benchmark.traceprocessor.TraceProcessor
1116import androidx.test.platform.app.InstrumentationRegistry
1217import org.junit.rules.TestRule
1318import org.junit.runner.Description
1419import org.junit.runners.model.Statement
1520
21+ @OptIn(ExperimentalMetricApi ::class )
22+ private class NoOpMetric : TraceMetric () {
23+ override fun getMeasurements (
24+ captureInfo : Metric .CaptureInfo ,
25+ traceSession : TraceProcessor .Session
26+ ): List <Measurement > = listOf (Measurement (" francis.placeholder" , 0.0 ))
27+ }
28+
1629class FrancisBenchmarkRule : TestRule {
1730 private val macrobenchmarkRule = MacrobenchmarkRule ()
1831
1932 override fun apply (base : Statement , description : Description ): Statement {
2033 return macrobenchmarkRule.apply (base, description)
2134 }
2235
36+ @OptIn(ExperimentalBenchmarkConfigApi ::class , ExperimentalPerfettoCaptureApi ::class )
2337 fun measureRepeated (
2438 packageName : String ,
2539 metrics : List <Metric >,
@@ -29,17 +43,34 @@ class FrancisBenchmarkRule : TestRule {
2943 setupBlock : MacrobenchmarkScope .() -> Unit = {},
3044 measureBlock : MacrobenchmarkScope .() -> Unit
3145 ) {
32- macrobenchmarkRule.measureRepeated(
33- packageName = packageName,
34- metrics = metrics,
35- compilationMode = compilationMode,
36- startupMode = startupMode,
37- iterations = francisIterations ? : iterations,
38- setupBlock = setupBlock,
39- measureBlock = wrapMeasureBlock(measureBlock)
40- )
46+ if (francisProfiler == " perfetto" ) {
47+ @OptIn(ExperimentalMetricApi ::class )
48+ macrobenchmarkRule.measureRepeated(
49+ packageName = packageName,
50+ metrics = listOf (NoOpMetric ()),
51+ iterations = francisIterations ? : iterations,
52+ experimentalConfig = ExperimentalConfig (
53+ perfettoConfig = createPerfettoConfig(packageName)
54+ ),
55+ compilationMode = compilationMode,
56+ startupMode = startupMode,
57+ setupBlock = setupBlock,
58+ measureBlock = measureBlock
59+ )
60+ } else {
61+ macrobenchmarkRule.measureRepeated(
62+ packageName = packageName,
63+ metrics = metrics,
64+ compilationMode = compilationMode,
65+ startupMode = startupMode,
66+ iterations = francisIterations ? : iterations,
67+ setupBlock = setupBlock,
68+ measureBlock = wrapMeasureBlock(measureBlock)
69+ )
70+ }
4171 }
4272
73+ @OptIn(ExperimentalPerfettoCaptureApi ::class )
4374 @ExperimentalBenchmarkConfigApi
4475 fun measureRepeated (
4576 packageName : String ,
@@ -51,17 +82,32 @@ class FrancisBenchmarkRule : TestRule {
5182 setupBlock : MacrobenchmarkScope .() -> Unit = {},
5283 measureBlock : MacrobenchmarkScope .() -> Unit
5384 ) {
54- @OptIn(ExperimentalPerfettoCaptureApi ::class )
55- macrobenchmarkRule.measureRepeated(
56- packageName = packageName,
57- metrics = metrics,
58- iterations = francisIterations ? : iterations,
59- experimentalConfig = experimentalConfig,
60- compilationMode = compilationMode,
61- startupMode = startupMode,
62- setupBlock = setupBlock,
63- measureBlock = wrapMeasureBlock(measureBlock)
64- )
85+ if (francisProfiler == " perfetto" ) {
86+ @OptIn(ExperimentalMetricApi ::class )
87+ macrobenchmarkRule.measureRepeated(
88+ packageName = packageName,
89+ metrics = listOf (NoOpMetric ()),
90+ iterations = francisIterations ? : iterations,
91+ experimentalConfig = ExperimentalConfig (
92+ perfettoConfig = createPerfettoConfig(packageName)
93+ ),
94+ compilationMode = compilationMode,
95+ startupMode = startupMode,
96+ setupBlock = setupBlock,
97+ measureBlock = measureBlock
98+ )
99+ } else {
100+ macrobenchmarkRule.measureRepeated(
101+ packageName = packageName,
102+ metrics = metrics,
103+ iterations = francisIterations ? : iterations,
104+ experimentalConfig = experimentalConfig,
105+ compilationMode = compilationMode,
106+ startupMode = startupMode,
107+ setupBlock = setupBlock,
108+ measureBlock = wrapMeasureBlock(measureBlock)
109+ )
110+ }
65111 }
66112
67113 private fun wrapMeasureBlock (
@@ -103,5 +149,65 @@ class FrancisBenchmarkRule : TestRule {
103149 private val simpleperfCallGraph: String? by lazy {
104150 args.getString(" simpleperfCallGraph" )
105151 }
152+
153+ @OptIn(ExperimentalPerfettoCaptureApi ::class )
154+ private fun createPerfettoConfig (packageName : String ): PerfettoConfig {
155+ return PerfettoConfig .Text (DEFAULT_PERFETTO_CONFIG .replace(" {PACKAGE}" , packageName))
156+ }
157+
158+ private val DEFAULT_PERFETTO_CONFIG = """
159+ buffers {
160+ size_kb: 65536
161+ fill_policy: RING_BUFFER
162+ }
163+ buffers {
164+ size_kb: 4096
165+ fill_policy: RING_BUFFER
166+ }
167+ data_sources {
168+ config {
169+ name: "linux.ftrace"
170+ target_buffer: 0
171+ ftrace_config {
172+ ftrace_events: "sched/sched_switch"
173+ ftrace_events: "sched/sched_wakeup"
174+ ftrace_events: "sched/sched_waking"
175+ ftrace_events: "sched/sched_blocked_reason"
176+ ftrace_events: "power/cpu_frequency"
177+ ftrace_events: "power/cpu_idle"
178+ ftrace_events: "power/suspend_resume"
179+ atrace_categories: "am"
180+ atrace_categories: "dalvik"
181+ atrace_categories: "gfx"
182+ atrace_categories: "input"
183+ atrace_categories: "pm"
184+ atrace_categories: "res"
185+ atrace_categories: "sched"
186+ atrace_categories: "view"
187+ atrace_categories: "wm"
188+ atrace_apps: "{PACKAGE}"
189+ }
190+ }
191+ }
192+ data_sources {
193+ config {
194+ name: "linux.process_stats"
195+ target_buffer: 1
196+ process_stats_config {
197+ scan_all_processes_on_start: true
198+ proc_stats_poll_ms: 1000
199+ }
200+ }
201+ }
202+ data_sources {
203+ config {
204+ name: "android.packages_list"
205+ target_buffer: 1
206+ }
207+ }
208+ write_into_file: true
209+ file_write_period_ms: 2500
210+ flush_period_ms: 5000
211+ """ .trimIndent()
106212 }
107213}
0 commit comments