Skip to content

Add etdump to android #10889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/android-perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ jobs:
PYTHON_EXECUTABLE=python bash .ci/scripts/build-qnn-sdk.sh
mkdir -p aar-out
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
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
mkdir -p extension/benchmark/android/benchmark/app/libs
cp aar-out/executorch.aar extension/benchmark/android/benchmark/app/libs
pushd extension/benchmark/android/benchmark
Expand Down
10 changes: 10 additions & 0 deletions extension/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ list(
fbjni
)

if(EXECUTORCH_ANDROID_PROFILING)
list(
APPEND
link_libraries
etdump
flatccrt
)
target_compile_definitions(executorch_jni PUBLIC EXECUTORCH_ANDROID_PROFILING=1)
endif()

if(TARGET optimized_native_cpu_ops_lib)
list(
APPEND
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ public String[] readLogBuffer() {
return mNativePeer.readLogBuffer();
}

/**
* Dump the ExecuTorch ETRecord file to /data/local/tmp/result.etdump.
*
* <p>Currently for internal (minibench) use only.
*
* @return true if the etdump was successfully written, false otherwise.
*/
@Experimental
public boolean etdump() {
return mNativePeer.etdump();
}

/**
* Explicitly destroys the native Module object. Calling this method is not required, as the
* native object will be destroyed when this object is garbage-collected. However, the timing of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ public void resetNative() {
/** Retrieve the in-memory log buffer, containing the most recent ExecuTorch log entries. */
@DoNotStrip
public native String[] readLogBuffer();

@DoNotStrip
public native boolean etdump();
}
49 changes: 45 additions & 4 deletions extension/android/jni/jni_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "jni_layer_constants.h"

#include <executorch/extension/android/jni/log.h>
Expand All @@ -32,6 +31,12 @@
#include <executorch/extension/threadpool/threadpool.h>
#endif

#ifdef EXECUTORCH_ANDROID_PROFILING
#include <executorch/devtools/etdump/etdump_flatcc.h>
#include <fcntl.h>
#include <unistd.h>
#endif

#include <fbjni/ByteBuffer.h>
#include <fbjni/fbjni.h>

Expand Down Expand Up @@ -238,8 +243,13 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
} else if (loadMode == 3) {
load_mode = Module::LoadMode::MmapUseMlockIgnoreErrors;
}

module_ = std::make_unique<Module>(modelPath->toStdString(), load_mode);
#ifdef EXECUTORCH_ANDROID_PROFILING
auto etdump_gen = std::make_unique<executorch::etdump::ETDumpGen>();
#else
auto etdump_gen = nullptr;
#endif
module_ = std::make_unique<Module>(
modelPath->toStdString(), load_mode, std::move(etdump_gen));

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

return jresult;
}

Expand Down Expand Up @@ -396,6 +405,37 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
#endif
}

jboolean etdump() {
#ifdef EXECUTORCH_ANDROID_PROFILING
executorch::etdump::ETDumpGen* etdumpgen =
(executorch::etdump::ETDumpGen*)module_->event_tracer();
auto etdump_data = etdumpgen->get_etdump_data();

if (etdump_data.buf != nullptr && etdump_data.size > 0) {
int etdump_file =
open("/data/local/tmp/result.etdump", O_WRONLY | O_CREAT, 0644);
if (etdump_file == -1) {
ET_LOG(Error, "Cannot create result.etdump error: %d", errno);
return false;
}
ssize_t bytes_written =
write(etdump_file, (uint8_t*)etdump_data.buf, etdump_data.size);
if (bytes_written == -1) {
ET_LOG(Error, "Cannot write result.etdump error: %d", errno);
return false;
} else {
ET_LOG(Info, "ETDump written %d bytes to file.", bytes_written);
}
close(etdump_file);
free(etdump_data.buf);
return true;
} else {
ET_LOG(Error, "No ETDump data available!");
}
#endif
return false;
}

facebook::jni::local_ref<facebook::jni::JArrayClass<jstring>> getUsedBackends(
facebook::jni::alias_ref<jstring> methodName) {
auto methodMeta = module_->method_meta(methodName->toStdString()).get();
Expand Down Expand Up @@ -423,6 +463,7 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {
makeNativeMethod("execute", ExecuTorchJni::execute),
makeNativeMethod("loadMethod", ExecuTorchJni::load_method),
makeNativeMethod("readLogBuffer", ExecuTorchJni::readLogBuffer),
makeNativeMethod("etdump", ExecuTorchJni::etdump),
makeNativeMethod("getUsedBackends", ExecuTorchJni::getUsedBackends),
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ phases:

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

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

adb -s $DEVICEFARM_DEVICE_UDID pull /data/local/tmp/result.etdump $DEVICEFARM_LOG_DIR/result.etdump

artifacts:
# By default, Device Farm will collect your artifacts from the $DEVICEFARM_LOG_DIR directory.
- $DEVICEFARM_LOG_DIR
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public void runBenchmark(
latency.add(forwardMs);
}

module.etdump();

final BenchmarkMetric.BenchmarkModel benchmarkModel =
BenchmarkMetric.extractBackendAndQuantization(model.getName().replace(".pte", ""));
// The list of metrics we have atm includes:
Expand Down
3 changes: 3 additions & 0 deletions scripts/build_android_library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ build_android_native_library() {
-DANDROID_PLATFORM=android-26 \
-DBUILD_TESTING=OFF \
-DEXECUTORCH_ENABLE_LOGGING=ON \
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
-DEXECUTORCH_ENABLE_EVENT_TRACER="${EXECUTORCH_ANDROID_PROFILING:-OFF}" \
-DEXECUTORCH_LOG_LEVEL=Info \
-DEXECUTORCH_BUILD_XNNPACK=ON \
-DEXECUTORCH_XNNPACK_SHARED_WORKSPACE=ON \
Expand Down Expand Up @@ -75,6 +77,7 @@ build_android_native_library() {
-DEXECUTORCH_ENABLE_LOGGING=ON \
-DEXECUTORCH_LOG_LEVEL=Info \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
-DEXECUTORCH_ANDROID_PROFILING="${EXECUTORCH_ANDROID_PROFILING:-OFF}" \
-DNEURON_BUFFER_ALLOCATOR_LIB="$NEURON_BUFFER_ALLOCATOR_LIB" \
-DEXECUTORCH_BUILD_KERNELS_CUSTOM="${EXECUTORCH_BUILD_EXTENSION_LLM:-ON}" \
-DEXECUTORCH_BUILD_LLAMA_JNI="${EXECUTORCH_BUILD_EXTENSION_LLM:-ON}" \
Expand Down
Loading