Skip to content

Commit 7d9b15f

Browse files
authored
Add etdump to android
Differential Revision: D75024936 Pull Request resolved: #10889
1 parent b73f9d5 commit 7d9b15f

File tree

8 files changed

+79
-5
lines changed

8 files changed

+79
-5
lines changed

.github/workflows/android-perf.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ jobs:
367367
PYTHON_EXECUTABLE=python bash .ci/scripts/build-qnn-sdk.sh
368368
369369
mkdir -p aar-out
370-
PYTHON_EXECUTABLE=python ANDROID_ABIS="arm64-v8a" BUILD_AAR_DIR=aar-out EXECUTORCH_BUILD_QNN=ON QNN_SDK_ROOT=/tmp/qnn/2.28.0.241029 bash scripts/build_android_library.sh
370+
PYTHON_EXECUTABLE=python ANDROID_ABIS="arm64-v8a" BUILD_AAR_DIR=aar-out EXECUTORCH_BUILD_QNN=ON QNN_SDK_ROOT=/tmp/qnn/2.28.0.241029 EXECUTORCH_ANDROID_PROFILING=ON bash scripts/build_android_library.sh
371371
mkdir -p extension/benchmark/android/benchmark/app/libs
372372
cp aar-out/executorch.aar extension/benchmark/android/benchmark/app/libs
373373
pushd extension/benchmark/android/benchmark

extension/android/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ list(
8080
fbjni
8181
)
8282

83+
if(EXECUTORCH_ANDROID_PROFILING)
84+
list(
85+
APPEND
86+
link_libraries
87+
etdump
88+
flatccrt
89+
)
90+
target_compile_definitions(executorch_jni PUBLIC EXECUTORCH_ANDROID_PROFILING=1)
91+
endif()
92+
8393
if(TARGET optimized_native_cpu_ops_lib)
8494
list(
8595
APPEND

extension/android/executorch_android/src/main/java/org/pytorch/executorch/Module.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ public String[] readLogBuffer() {
152152
return mNativePeer.readLogBuffer();
153153
}
154154

155+
/**
156+
* Dump the ExecuTorch ETRecord file to /data/local/tmp/result.etdump.
157+
*
158+
* <p>Currently for internal (minibench) use only.
159+
*
160+
* @return true if the etdump was successfully written, false otherwise.
161+
*/
162+
@Experimental
163+
public boolean etdump() {
164+
return mNativePeer.etdump();
165+
}
166+
155167
/**
156168
* Explicitly destroys the native Module object. Calling this method is not required, as the
157169
* native object will be destroyed when this object is garbage-collected. However, the timing of

extension/android/executorch_android/src/main/java/org/pytorch/executorch/NativePeer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,7 @@ public void resetNative() {
6262
/** Retrieve the in-memory log buffer, containing the most recent ExecuTorch log entries. */
6363
@DoNotStrip
6464
public native String[] readLogBuffer();
65+
66+
@DoNotStrip
67+
public native boolean etdump();
6568
}

extension/android/jni/jni_layer.cpp

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <unordered_map>
1616
#include <unordered_set>
1717
#include <vector>
18-
1918
#include "jni_layer_constants.h"
2019

2120
#include <executorch/extension/android/jni/log.h>
@@ -32,6 +31,12 @@
3231
#include <executorch/extension/threadpool/threadpool.h>
3332
#endif
3433

34+
#ifdef EXECUTORCH_ANDROID_PROFILING
35+
#include <executorch/devtools/etdump/etdump_flatcc.h>
36+
#include <fcntl.h>
37+
#include <unistd.h>
38+
#endif
39+
3540
#include <fbjni/ByteBuffer.h>
3641
#include <fbjni/fbjni.h>
3742

@@ -238,8 +243,13 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
238243
} else if (loadMode == 3) {
239244
load_mode = Module::LoadMode::MmapUseMlockIgnoreErrors;
240245
}
241-
242-
module_ = std::make_unique<Module>(modelPath->toStdString(), load_mode);
246+
#ifdef EXECUTORCH_ANDROID_PROFILING
247+
auto etdump_gen = std::make_unique<executorch::etdump::ETDumpGen>();
248+
#else
249+
auto etdump_gen = nullptr;
250+
#endif
251+
module_ = std::make_unique<Module>(
252+
modelPath->toStdString(), load_mode, std::move(etdump_gen));
243253

244254
#ifdef ET_USE_THREADPOOL
245255
// Default to using cores/2 threadpool threads. The long-term plan is to
@@ -362,7 +372,6 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
362372
auto jevalue = JEValue::newJEValueFromEValue(result.get()[i]);
363373
jresult->setElement(i, *jevalue);
364374
}
365-
366375
return jresult;
367376
}
368377

@@ -396,6 +405,37 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
396405
#endif
397406
}
398407

408+
jboolean etdump() {
409+
#ifdef EXECUTORCH_ANDROID_PROFILING
410+
executorch::etdump::ETDumpGen* etdumpgen =
411+
(executorch::etdump::ETDumpGen*)module_->event_tracer();
412+
auto etdump_data = etdumpgen->get_etdump_data();
413+
414+
if (etdump_data.buf != nullptr && etdump_data.size > 0) {
415+
int etdump_file =
416+
open("/data/local/tmp/result.etdump", O_WRONLY | O_CREAT, 0644);
417+
if (etdump_file == -1) {
418+
ET_LOG(Error, "Cannot create result.etdump error: %d", errno);
419+
return false;
420+
}
421+
ssize_t bytes_written =
422+
write(etdump_file, (uint8_t*)etdump_data.buf, etdump_data.size);
423+
if (bytes_written == -1) {
424+
ET_LOG(Error, "Cannot write result.etdump error: %d", errno);
425+
return false;
426+
} else {
427+
ET_LOG(Info, "ETDump written %d bytes to file.", bytes_written);
428+
}
429+
close(etdump_file);
430+
free(etdump_data.buf);
431+
return true;
432+
} else {
433+
ET_LOG(Error, "No ETDump data available!");
434+
}
435+
#endif
436+
return false;
437+
}
438+
399439
facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>> getUsedBackends(
400440
facebook::jni::alias_ref<jstring> methodName) {
401441
auto methodMeta = module_->method_meta(methodName->toStdString()).get();
@@ -423,6 +463,7 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
423463
makeNativeMethod("execute", ExecuTorchJni::execute),
424464
makeNativeMethod("loadMethod", ExecuTorchJni::load_method),
425465
makeNativeMethod("readLogBuffer", ExecuTorchJni::readLogBuffer),
466+
makeNativeMethod("etdump", ExecuTorchJni::etdump),
426467
makeNativeMethod("getUsedBackends", ExecuTorchJni::getUsedBackends),
427468
});
428469
}

extension/benchmark/android/benchmark/android-llm-device-farm-test-spec.yml.j2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ phases:
107107

108108
- echo "Run benchmark"
109109
- |
110+
adb -s $DEVICEFARM_DEVICE_UDID shell touch /data/local/tmp/result.etdump
110111
adb -s $DEVICEFARM_DEVICE_UDID shell am force-stop org.pytorch.minibench
111112

112113
adb -s $DEVICEFARM_DEVICE_UDID shell dumpsys deviceidle force-idle
@@ -147,6 +148,8 @@ phases:
147148
# Trying to pull the file using adb ends up with permission error, but this works too, so why not
148149
echo "${BENCHMARK_RESULTS}" > $DEVICEFARM_LOG_DIR/benchmark_results.json
149150

151+
adb -s $DEVICEFARM_DEVICE_UDID pull /data/local/tmp/result.etdump $DEVICEFARM_LOG_DIR/result.etdump
152+
150153
artifacts:
151154
# By default, Device Farm will collect your artifacts from the $DEVICEFARM_LOG_DIR directory.
152155
- $DEVICEFARM_LOG_DIR

extension/benchmark/android/benchmark/app/src/main/java/org/pytorch/minibench/ModelRunner.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public void runBenchmark(
4141
latency.add(forwardMs);
4242
}
4343

44+
module.etdump();
45+
4446
final BenchmarkMetric.BenchmarkModel benchmarkModel =
4547
BenchmarkMetric.extractBackendAndQuantization(model.getName().replace(".pte", ""));
4648
// The list of metrics we have atm includes:

scripts/build_android_library.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ build_android_native_library() {
4040
-DANDROID_PLATFORM=android-26 \
4141
-DBUILD_TESTING=OFF \
4242
-DEXECUTORCH_ENABLE_LOGGING=ON \
43+
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
44+
-DEXECUTORCH_ENABLE_EVENT_TRACER="${EXECUTORCH_ANDROID_PROFILING:-OFF}" \
4345
-DEXECUTORCH_LOG_LEVEL=Info \
4446
-DEXECUTORCH_BUILD_XNNPACK=ON \
4547
-DEXECUTORCH_XNNPACK_SHARED_WORKSPACE=ON \
@@ -75,6 +77,7 @@ build_android_native_library() {
7577
-DEXECUTORCH_ENABLE_LOGGING=ON \
7678
-DEXECUTORCH_LOG_LEVEL=Info \
7779
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
80+
-DEXECUTORCH_ANDROID_PROFILING="${EXECUTORCH_ANDROID_PROFILING:-OFF}" \
7881
-DNEURON_BUFFER_ALLOCATOR_LIB="$NEURON_BUFFER_ALLOCATOR_LIB" \
7982
-DEXECUTORCH_BUILD_KERNELS_CUSTOM="${EXECUTORCH_BUILD_EXTENSION_LLM:-ON}" \
8083
-DEXECUTORCH_BUILD_LLAMA_JNI="${EXECUTORCH_BUILD_EXTENSION_LLM:-ON}" \

0 commit comments

Comments
 (0)