Skip to content

Commit 38fdfae

Browse files
authored
Add Buck bindings for Android benchmark script (#18853) (#18853)
Summary: Add buck bindings for the new android benchmark script. It runs a PTE on a locally connected device via adb. Note that this path isn't supported in OSS (use the CMake version to get the same functionality). Differential Revision: D100254703
1 parent 107eb92 commit 38fdfae

3 files changed

Lines changed: 102 additions & 25 deletions

File tree

devtools/scripts/BUCK

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
load("@fbcode_macros//build_defs:build_file_migration.bzl", "non_fbcode_target")
2+
3+
oncall("executorch")
4+
5+
non_fbcode_target(
6+
_kind = native.sh_binary,
7+
name = "_benchmark_android_sh",
8+
main = "benchmark_android.sh",
9+
)
10+
11+
non_fbcode_target(
12+
_kind = native.command_alias,
13+
name = "benchmark_android",
14+
exe = ":_benchmark_android_sh",
15+
args = ["--build-tool", "buck"],
16+
)

devtools/scripts/benchmark_android.sh

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,47 @@
1414
# ./devtools/scripts/benchmark_android.sh <model.pte> [options]
1515
#
1616
# Options:
17+
# --build-tool <tool> Build system: cmake (default) or buck
1718
# --warmup <N> Number of warmup executions (default: 1)
1819
# --iterations <N> Number of timed executions (default: 10)
1920
# --num-threads <N> CPU threads for inference (default: -1, auto-detect)
2021
# --method <name> Method to run (default: first method in the program)
2122
# --backends <list> Comma-separated backends (default: xnnpack)
2223
# Supported: xnnpack, coreml, vulkan, qnn
24+
# (cmake only; buck links all backends)
2325
# --device <serial> ADB device serial (for multiple devices)
2426
# --etdump Enable event tracer and pull etdump back to host
2527
# --no-cleanup Leave model file on device after benchmarking
26-
# --rebuild Force cmake reconfigure and rebuild
27-
# --build-dir <path> Reuse existing build directory (skip build step)
28+
# --rebuild Force cmake reconfigure and rebuild (cmake only)
29+
# --build-dir <path> Reuse existing build directory (cmake only)
2830

2931
set -euo pipefail
3032

31-
# --- Locate ExecuTorch root from script path ---
32-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
33-
EXECUTORCH_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
33+
# Pre-scan for --build-tool (needed before ExecuTorch root validation).
34+
BUILD_TOOL="cmake"
35+
_prev=""
36+
for _arg in "$@"; do
37+
if [[ "$_prev" == "--build-tool" ]]; then BUILD_TOOL="$_arg"; break; fi
38+
_prev="$_arg"
39+
done
40+
unset _prev _arg
3441

35-
if [[ ! -f "$EXECUTORCH_ROOT/CMakeLists.txt" ]] || [[ ! -d "$EXECUTORCH_ROOT/devtools" ]]; then
36-
echo "Error: Could not locate ExecuTorch root from script path: $SCRIPT_DIR"
37-
exit 1
38-
fi
42+
# --- Locate ExecuTorch root from script path (cmake only) ---
43+
if [[ "$BUILD_TOOL" != "buck" ]]; then
44+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
45+
EXECUTORCH_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
3946

40-
cd "$EXECUTORCH_ROOT"
47+
if [[ ! -f "$EXECUTORCH_ROOT/CMakeLists.txt" ]] || [[ ! -d "$EXECUTORCH_ROOT/devtools" ]]; then
48+
echo "Error: Could not locate ExecuTorch root from script path: $SCRIPT_DIR"
49+
exit 1
50+
fi
51+
52+
cd "$EXECUTORCH_ROOT"
53+
fi
4154

4255
# --- Defaults ---
4356
MODEL_PATH=""
57+
# BUILD_TOOL is set by pre-scan above; re-declare here for documentation.
4458
WARMUP=1
4559
ITERATIONS=10
4660
NUM_THREADS=-1
@@ -60,23 +74,25 @@ usage() {
6074
Usage: $0 <model.pte> [options]
6175
6276
Options:
77+
--build-tool <tool> Build system: cmake (default) or buck
6378
--warmup <N> Number of warmup executions (default: 1)
6479
--iterations <N> Number of timed executions (default: 10)
6580
--num-threads <N> CPU threads for inference (default: -1, auto-detect)
6681
--method <name> Method to run (default: first method in the program)
6782
--backends <list> Comma-separated backends to build (default: xnnpack)
68-
Supported: xnnpack, vulkan, qnn
83+
Supported: xnnpack, vulkan, qnn (cmake only)
6984
--device <serial> ADB device serial (for multiple devices)
7085
--etdump Enable event tracer and pull etdump back to host
7186
--no-cleanup Leave model file on device after benchmarking
72-
--rebuild Force cmake reconfigure and rebuild
73-
--build-dir <path> Reuse existing build directory (skip build step)
87+
--rebuild Force cmake reconfigure and rebuild (cmake only)
88+
--build-dir <path> Reuse existing build directory (cmake only)
7489
EOF
7590
exit 1
7691
}
7792

7893
while [[ $# -gt 0 ]]; do
7994
case "$1" in
95+
--build-tool) BUILD_TOOL="$2"; shift 2 ;;
8096
--warmup) WARMUP="$2"; shift 2 ;;
8197
--iterations) ITERATIONS="$2"; shift 2 ;;
8298
--num-threads) NUM_THREADS="$2"; shift 2 ;;
@@ -167,7 +183,34 @@ find_ndk() {
167183
}
168184

169185
# --- Build executor_runner ---
170-
if [[ -z "$BUILD_DIR" ]]; then
186+
if [[ "$BUILD_TOOL" == "buck" ]]; then
187+
BUCK_TARGET="fbsource//xplat/executorch/examples/portable/executor_runner:executor_runner_optAndroid#android-arm64"
188+
BUCK_ARGS=(
189+
@fbsource//fbandroid/mode/static_linking
190+
@fbsource//fbandroid/mode/opt
191+
--config cxx.default_platform=android-arm64
192+
)
193+
if [[ "$ETDUMP" == true ]]; then
194+
BUCK_ARGS+=(-c executorch.event_tracer_enabled=true)
195+
fi
196+
echo "Building executor_runner with Buck..."
197+
BUCK_BUILD_OUTPUT=$(mktemp)
198+
if ! buck2 build "${BUCK_ARGS[@]}" "$BUCK_TARGET" --show-output >"$BUCK_BUILD_OUTPUT" 2>&1; then
199+
echo "Error: Buck build failed."
200+
cat "$BUCK_BUILD_OUTPUT"
201+
rm -f "$BUCK_BUILD_OUTPUT"
202+
exit 1
203+
fi
204+
# --show-output strips the #flavor suffix, so match on target without it.
205+
BUCK_TARGET_NO_FLAVOR="${BUCK_TARGET%%#*}"
206+
RUNNER_BIN=$(grep "$BUCK_TARGET_NO_FLAVOR" "$BUCK_BUILD_OUTPUT" | awk '{print $2}')
207+
rm -f "$BUCK_BUILD_OUTPUT"
208+
if [[ -z "$RUNNER_BIN" || ! -f "$RUNNER_BIN" ]]; then
209+
echo "Error: Could not locate output binary from buck build."
210+
exit 1
211+
fi
212+
echo "Build complete."
213+
elif [[ -z "$BUILD_DIR" ]]; then
171214
BUILD_DIR="cmake-out-android-benchmark"
172215

173216
ANDROID_NDK=$(find_ndk)
@@ -244,26 +287,30 @@ else
244287
echo "Using existing build directory: $BUILD_DIR"
245288
fi
246289

247-
RUNNER_BIN="$BUILD_DIR/executor_runner"
248-
if [[ ! -f "$RUNNER_BIN" ]]; then
249-
echo "Error: executor_runner not found at $RUNNER_BIN"
250-
exit 1
290+
# RUNNER_BIN is set by the buck build path above; for cmake, derive it here.
291+
if [[ "$BUILD_TOOL" != "buck" ]]; then
292+
RUNNER_BIN="$BUILD_DIR/executor_runner"
293+
if [[ ! -f "$RUNNER_BIN" ]]; then
294+
echo "Error: executor_runner not found at $RUNNER_BIN"
295+
exit 1
296+
fi
251297
fi
252298

253299
# --- Push to device ---
300+
RUNNER_NAME=$(basename "$RUNNER_BIN")
254301
echo "Pushing files to device..."
255302
adb_cmd shell mkdir -p "$DEVICE_DIR"
256303
adb_cmd push --sync "$RUNNER_BIN" "$DEVICE_DIR/"
257304
adb_cmd push --sync "$MODEL_PATH" "$DEVICE_DIR/"
258-
adb_cmd shell chmod +x "$DEVICE_DIR/executor_runner"
305+
adb_cmd shell chmod +x "$DEVICE_DIR/$RUNNER_NAME"
259306

260307
DEVICE_MODEL="$DEVICE_DIR/$MODEL_NAME"
261308

262309
# --- Runner args ---
263310
runner_args=(
264311
"--model_path=$DEVICE_MODEL"
265312
"--cpu_threads=$NUM_THREADS"
266-
"--print_output=false"
313+
"--print_output=none"
267314
)
268315

269316
if [[ -n "$METHOD" ]]; then
@@ -274,7 +321,7 @@ fi
274321
RUNNER_OUTPUT=$(mktemp)
275322
run_on_device() {
276323
local rc=0
277-
adb_cmd shell "$DEVICE_DIR/executor_runner" "$@" > "$RUNNER_OUTPUT" 2>&1 || rc=$?
324+
adb_cmd shell "$DEVICE_DIR/$RUNNER_NAME" "$@" > "$RUNNER_OUTPUT" 2>&1 || rc=$?
278325
if [[ "$rc" -ne 0 ]]; then
279326
echo ""
280327
echo "Error: executor_runner exited with code $rc"
@@ -293,7 +340,12 @@ run_on_device() {
293340
# --- Warmup ---
294341
if [[ "$WARMUP" -gt 0 ]]; then
295342
echo "Running $WARMUP warmup iteration(s)..."
296-
run_on_device "${runner_args[@]}" "--num_executions=$WARMUP"
343+
warmup_args=("${runner_args[@]}" "--num_executions=$WARMUP")
344+
if [[ "$ETDUMP" == true ]]; then
345+
warmup_args+=("--etdump_path=$DEVICE_DIR/warmup.etdump")
346+
fi
347+
run_on_device "${warmup_args[@]}"
348+
adb_cmd shell rm -f "$DEVICE_DIR/warmup.etdump"
297349
fi
298350

299351
# Clear logcat after warmup so the benchmark progress reader doesn't pick up
@@ -362,9 +414,17 @@ if [[ "$ETDUMP" == true ]]; then
362414

363415
# Run the inspector CLI to print a tabular summary.
364416
echo ""
365-
"$EXECUTORCH_ROOT/run_python_script.sh" \
366-
"$EXECUTORCH_ROOT/devtools/inspector/inspector_cli.py" \
367-
--etdump_path="$ETDUMP_LOCAL"
417+
if [[ "$BUILD_TOOL" == "buck" ]]; then
418+
if ! buck2 run fbcode//executorch/devtools/inspector:inspector_cli -- \
419+
--etdump_path="$ETDUMP_LOCAL" 2>&1; then
420+
echo "Warning: inspector CLI failed. Analyze the ETDump manually:"
421+
echo " buck2 run fbcode//executorch/devtools/inspector:inspector_cli -- --etdump_path=$ETDUMP_LOCAL"
422+
fi
423+
else
424+
"$EXECUTORCH_ROOT/run_python_script.sh" \
425+
"$EXECUTORCH_ROOT/devtools/inspector/inspector_cli.py" \
426+
--etdump_path="$ETDUMP_LOCAL"
427+
fi
368428
fi
369429

370430
# --- Cleanup ---

examples/portable/executor_runner/targets.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def define_common_targets():
3838
compiler_flags = ["-Wno-global-constructors"],
3939
deps = [
4040
"//executorch/runtime/executor:program",
41+
"//executorch/devtools/etdump:etdump_flatcc",
4142
"//executorch/extension/data_loader:file_data_loader",
4243
"//executorch/extension/data_loader:buffer_data_loader",
4344
"//executorch/extension/evalue_util:print_evalue",

0 commit comments

Comments
 (0)