Skip to content

Commit 746709a

Browse files
Make screen timeout configurable and validate cold startup LaunchState
Add --screen-timeout-ms CLI argument (default 1800000 = 30 min) and ScreenTimeoutMs MSBuild property so the screen timeout can be tuned from the .proj file without code changes. Add LaunchState validation to AndroidHelper.measure_cold_startup(): if am start reports anything other than COLD (e.g. UNKNOWN when the screen is off), the method now throws with a clear diagnostic message suggesting to increase --screen-timeout-ms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3f5e643 commit 746709a

3 files changed

Lines changed: 19 additions & 3 deletions

File tree

eng/performance/maui_scenarios_android_innerloop.proj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333

3434
<RunConfigsString>$(RuntimeFlavor)_$(CodegenType)</RunConfigsString>
3535
<InnerLoopIterations Condition="'$(InnerLoopIterations)' == ''">10</InnerLoopIterations>
36+
<!-- Screen timeout must be large enough so the display stays on for the entire scenario.
37+
If the screen turns off mid-run, am start reports LaunchState: UNKNOWN and omits
38+
TotalTime, which breaks cold startup measurement. -->
39+
<ScreenTimeoutMs Condition="'$(ScreenTimeoutMs)' == ''">1800000</ScreenTimeoutMs>
3640
</PropertyGroup>
3741

3842
<!-- Remove .NET SDK packs from the Helix correlation payload to reduce transfer size.
@@ -77,7 +81,7 @@
7781
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
7882
<HelixWorkItem Include="@(MAUIAndroidInnerLoopScenario -> 'Inner Loop Device - %(Identity)')">
7983
<PreCommands>$(_WindowsEnvVars);$(Python) setup_helix.py $(PERFLAB_Framework)-android &quot;$(_MSBuildArgs)&quot;</PreCommands>
80-
<Command>$(Python) test.py androidinnerloop --csproj-path app/MauiAndroidInnerLoop.csproj --edit-src &quot;src/MainPage.xaml.cs;src/MainPage.xaml&quot; --edit-dest &quot;app/Pages/MainPage.xaml.cs;app/Pages/MainPage.xaml&quot; --package-name com.companyname.mauiandroidinnerloop -f $(PERFLAB_Framework)-android -c Debug --msbuild-args &quot;$(_MSBuildArgs)&quot; --scenario-name &quot;%(Identity)&quot; --inner-loop-iterations $(InnerLoopIterations) $(ScenarioArgs)</Command>
84+
<Command>$(Python) test.py androidinnerloop --csproj-path app/MauiAndroidInnerLoop.csproj --edit-src &quot;src/MainPage.xaml.cs;src/MainPage.xaml&quot; --edit-dest &quot;app/Pages/MainPage.xaml.cs;app/Pages/MainPage.xaml&quot; --package-name com.companyname.mauiandroidinnerloop -f $(PERFLAB_Framework)-android -c Debug --msbuild-args &quot;$(_MSBuildArgs)&quot; --scenario-name &quot;%(Identity)&quot; --inner-loop-iterations $(InnerLoopIterations) --screen-timeout-ms $(ScreenTimeoutMs) $(ScenarioArgs)</Command>
8185
<PostCommands>$(Python) post.py</PostCommands>
8286
<DownloadFilesFromResults>output.log</DownloadFilesFromResults>
8387
</HelixWorkItem>
@@ -87,7 +91,7 @@
8791
<ItemGroup Condition="'$(TargetsWindows)' != 'true'">
8892
<HelixWorkItem Include="@(MAUIAndroidInnerLoopScenario -> 'Inner Loop Emulator - %(Identity)')">
8993
<PreCommands>$(_LinuxEnvVars);$(Python) setup_helix.py $(PERFLAB_Framework)-android &quot;$(_MSBuildArgs)&quot;</PreCommands>
90-
<Command>$(Python) test.py androidinnerloop --csproj-path app/MauiAndroidInnerLoop.csproj --edit-src &quot;src/MainPage.xaml.cs;src/MainPage.xaml&quot; --edit-dest &quot;app/Pages/MainPage.xaml.cs;app/Pages/MainPage.xaml&quot; --package-name com.companyname.mauiandroidinnerloop -f $(PERFLAB_Framework)-android -c Debug --msbuild-args &quot;$(_MSBuildArgs)&quot; --scenario-name &quot;%(Identity)&quot; --inner-loop-iterations $(InnerLoopIterations) $(ScenarioArgs)</Command>
94+
<Command>$(Python) test.py androidinnerloop --csproj-path app/MauiAndroidInnerLoop.csproj --edit-src &quot;src/MainPage.xaml.cs;src/MainPage.xaml&quot; --edit-dest &quot;app/Pages/MainPage.xaml.cs;app/Pages/MainPage.xaml&quot; --package-name com.companyname.mauiandroidinnerloop -f $(PERFLAB_Framework)-android -c Debug --msbuild-args &quot;$(_MSBuildArgs)&quot; --scenario-name &quot;%(Identity)&quot; --inner-loop-iterations $(InnerLoopIterations) --screen-timeout-ms $(ScreenTimeoutMs) $(ScenarioArgs)</Command>
9195
<PostCommands>$(Python) post.py</PostCommands>
9296
<DownloadFilesFromResults>output.log</DownloadFilesFromResults>
9397
</HelixWorkItem>

src/scenarios/shared/androidhelper.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,16 @@ def measure_cold_startup(self, packagename: str, activityname: str) -> int:
301301
# Primary: parse TotalTime or WaitTime from am start -W output
302302
total_match = re.search(r"TotalTime:\s*(\d+)", start_result.stdout)
303303
wait_match = re.search(r"WaitTime:\s*(\d+)", start_result.stdout)
304+
launch_state_match = re.search(r"LaunchState:\s*(\w+)", start_result.stdout)
305+
if launch_state_match:
306+
launch_state = launch_state_match.group(1)
307+
getLogger().info("LaunchState: %s" % launch_state)
308+
if launch_state != "COLD":
309+
raise Exception(
310+
"Expected LaunchState: COLD but got LaunchState: %s. "
311+
"If UNKNOWN, the device screen may have turned off mid-run — "
312+
"increase --screen-timeout-ms." % launch_state
313+
)
304314
if total_match:
305315
startup_ms = int(total_match.group(1))
306316
getLogger().info("Startup time (TotalTime): %d ms" % startup_ms)

src/scenarios/shared/runner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def parseargs(self):
184184
androidinnerloopparser.add_argument('--msbuild-args', help='Additional MSBuild arguments', dest='msbuildargs', default='')
185185
androidinnerloopparser.add_argument('--package-name', help='Android package name for startup measurement (e.g. com.companyname.mauiandroidinnerloop)', dest='packagename')
186186
androidinnerloopparser.add_argument('--inner-loop-iterations', help='Number of incremental build+deploy+startup iterations (1+)', type=int, default=10, dest='innerloopiterations')
187+
androidinnerloopparser.add_argument('--screen-timeout-ms', help='Screen timeout in milliseconds. Must be large enough so the display stays on for the entire scenario; a screen-off mid-run breaks cold startup measurement (am start reports LaunchState: UNKNOWN).', type=int, default=30 * 60 * 1000, dest='screentimeoutms')
187188
self.add_common_arguments(androidinnerloopparser)
188189

189190
args = parser.parse_args()
@@ -218,6 +219,7 @@ def parseargs(self):
218219
self.msbuildargs = args.msbuildargs or os.environ.get('PERFLAB_MSBUILD_ARGS', '')
219220
self.packagename = args.packagename
220221
self.innerloopiterations = args.innerloopiterations
222+
self.screentimeoutms = args.screentimeoutms
221223

222224
if self.testtype == const.DEVICESTARTUP:
223225
self.packagepath = args.packagepath
@@ -1120,7 +1122,7 @@ def run_incremental_iteration(iteration, num_iterations, base_cmd, edit_pairs,
11201122
# measurement impossible.
11211123
androidHelper = AndroidHelper()
11221124
try:
1123-
androidHelper.setup_device(self.packagename, packagepath=None, animationsdisabled=True, skip_install=True, skip_xharness_warmup=True, skip_package_verifier=True, skip_test_launch=True, screen_timeout_ms=30 * 60 * 1000)
1125+
androidHelper.setup_device(self.packagename, packagepath=None, animationsdisabled=True, skip_install=True, skip_xharness_warmup=True, skip_package_verifier=True, skip_test_launch=True, screen_timeout_ms=self.screentimeoutms)
11241126

11251127
activityname = androidHelper.activityname
11261128
getLogger().info("Using resolved activity: %s" % activityname)

0 commit comments

Comments
 (0)