Files
file-manager/tools/benchmark-fixture.sh
T
SoftwareApp 3d8f351d12 Make the benchmark fixture reusable, since building it is the expensive part
I wrote in PERFORMANCE.md that twenty thousand files are an argument for building the fixture once and keeping it, and then deleted it after the run - twice. The script now makes keeping it the default: create leaves a folder alone when it already holds at least the requested number of files, prints what it found, and still re-grants storage because a reinstall clears app-ops. --fresh rebuilds. Verified by running --count 300 twice and watching the second call reuse.
2026-10-17 21:04:25 +02:00

73 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Prepares the device for the macrobenchmark module, and takes it back afterwards.
#
# ./tools/benchmark-fixture.sh # create the folder, grant storage access
# ./tools/benchmark-fixture.sh --remove # delete the folder again
#
# Why this is a script rather than setup inside the benchmark: UiAutomation's executeShellCommand
# runs with the *test app's* uid, not the shell's, so it cannot write to /sdcard and cannot grant
# itself an app-op. The first version of the benchmark tried exactly that and failed with a
# RuntimeException from UiAutomationConnection, leaving no fixture and a hang. Through adb the same
# commands run as the shell user, which has the rights this needs.
#
# The folder is at the root of shared storage under a name that sorts before everything else, so the
# benchmark finds its row without scrolling.
set -euo pipefail
package=de.softwareapp_hb.filemanager
directory=/sdcard/AABenchmark
count=1000
# The size is a knob because the interesting question is how the browser scales: 1 000 files is what the
# benchmark uses by default, and 5 000 or 20 000 is the same run with a bigger folder:
#
# ./tools/benchmark-fixture.sh --count 20000
#
# Creating is idempotent: a folder that already holds at least `--count` files is left alone, because
# building twenty thousand files through a phone's storage layer takes about half an hour and the fixture
# is worth keeping between runs. `--fresh` rebuilds it anyway.
if [ "${1:-}" = "--count" ]; then
count=${2:?"--count needs a number"}
case "$count" in
''|*[!0-9]*) echo "benchmark-fixture: --count needs a number, not '$count'" >&2; exit 2 ;;
esac
shift 2
fi
fresh=0
if [ "${1:-}" = "--fresh" ]; then
fresh=1
shift
fi
case "${1:-create}" in
--remove)
adb shell "rm -rf $directory"
echo "benchmark-fixture: removed $directory"
;;
create)
existing=$(adb shell "ls $directory 2>/dev/null | wc -l" | tr -d '\r ')
if [ "$fresh" -eq 0 ] && [ "${existing:-0}" -ge "$count" ]; then
echo "benchmark-fixture: reusing $directory ($existing files, $count asked for)"
else
# One shell loop with builtin redirection: no fork per file, so a thousand files take a
# moment rather than a minute.
adb shell "rm -rf $directory; mkdir -p $directory; \
i=0; while [ \$i -lt $count ]; do : > $directory/file-\$i.txt; i=\$((i+1)); done"
echo "benchmark-fixture: $count files in $directory"
fi
# The benchmark build is not the debug build, so it starts with no storage grant; granting it
# here is what lets the run be unattended. No `--uid`: that flag takes a uid, not a package
# name, and passing a package there grants nothing while still reporting that something was
# set — which is exactly the kind of half-truth that costs an afternoon. Re-granted even when the
# fixture is reused, because a reinstall of the app clears its app-ops.
adb shell "appops set $package MANAGE_EXTERNAL_STORAGE allow"
echo "benchmark-fixture: storage granted to $package"
;;
*)
echo "usage: $0 [--remove]" >&2
exit 2
;;
esac