Skip to content

Commit a4b59cc

Browse files
authored
Added ETDump to Wasm (#13304)
### Summary Turning on the `EXECUTORCH_ENABLE_EVENT_TRACER` option will enable event tracing in the Wasm module API. The results can be obtained with the `etdump()` method. ### Test plan Added two tests depending on whether `EXECUTORCH_ENABLE_EVENT_TRACER` is turned on or not. Added the `--enable-etdump` option to `scripts/build_wasm_tests.sh` which turns on the above option. Added configurations to the `unittest-wasm-bindings` CI test to run with and without `--enable-etdump`.
1 parent 5563051 commit a4b59cc

File tree

8 files changed

+165
-8
lines changed

8 files changed

+165
-8
lines changed

.github/workflows/pull.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,8 @@ jobs:
801801
id-token: write
802802
contents: read
803803
strategy:
804+
matrix:
805+
enable-etdump: ['', '--enable-etdump']
804806
fail-fast: false
805807
with:
806808
runner: linux.2xlarge
@@ -820,7 +822,7 @@ jobs:
820822
source .ci/scripts/setup-emscripten.sh
821823
822824
# Test selective build
823-
bash scripts/build_wasm_tests.sh
825+
bash scripts/build_wasm_tests.sh ${{ matrix.enable-etdump }}
824826
825827
# Install Jest
826828
cd cmake-out-wasm/extension/wasm/test

extension/wasm/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ list(
4444

4545
add_library(executorch_wasm OBJECT wasm_bindings.cpp)
4646

47+
if(EXECUTORCH_ENABLE_EVENT_TRACER)
48+
list(APPEND link_libraries etdump)
49+
target_compile_definitions(
50+
executorch_wasm PUBLIC EXECUTORCH_ENABLE_EVENT_TRACER
51+
)
52+
endif()
53+
4754
target_compile_options(executorch_wasm PUBLIC ${_common_compile_options})
4855
target_include_directories(
4956
executorch_wasm PUBLIC ${_common_include_directories}

extension/wasm/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ The output `my_project.js` should contain both the emitted JS code and the conte
8282
- `getMethods()`: Returns the list of methods in the model.
8383
- `loadMethod(methodName)`: Load a method from the model.
8484
- `getMethodMetadata(methodName)`: Get the metadata of a method.
85+
- `etdump()`: If enabled, flushes the etdump buffer and return the results.
8586
- `execute(methodName, inputs)`: Execute a method with the given inputs.
8687
- `forward(inputs)`: Execute the forward method with the given inputs.
8788
- `delete()`: Delete the model from memory.
@@ -118,6 +119,10 @@ The output `my_project.js` should contain both the emitted JS code and the conte
118119
- `name`: The name of the tensor.
119120
- These are value types and do not need to be manually deleted.
120121

122+
### ETDumpResult
123+
- `buffer`: The buffer containing the ETDump data.
124+
- `delete()`: Delete the ETDumpResult from memory.
125+
121126
### ScalarType
122127
- Only `Float` and `Long` are currently supported.
123128
- `value`: The int constant value of the enum.

extension/wasm/test/CMakeLists.txt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ add_custom_target(
4040
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/package.json
4141
)
4242

43+
if(EXECUTORCH_ENABLE_EVENT_TRACER)
44+
set(ETDUMP_UNIT_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/unittests_etdump.js)
45+
else()
46+
set(ETDUMP_UNIT_TESTS
47+
${CMAKE_CURRENT_SOURCE_DIR}/unittests_etdump_disabled.js
48+
)
49+
endif()
50+
51+
add_custom_command(
52+
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/unittests_full.js
53+
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/unittests.js ${ETDUMP_UNIT_TESTS} >
54+
${CMAKE_CURRENT_BINARY_DIR}/unittests_full.js
55+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/unittests.js ${ETDUMP_UNIT_TESTS}
56+
COMMENT "Copying unittests_full.js to build output directory"
57+
)
58+
59+
add_custom_target(
60+
executorch_wasm_unittests
61+
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/unittests_full.js
62+
)
63+
4364
add_executable(executorch_wasm_tests)
4465
target_link_libraries(executorch_wasm_tests PRIVATE executorch_wasm)
4566
target_link_options(
@@ -48,7 +69,7 @@ target_link_options(
4869
--embed-file
4970
"${MODELS_DIR}@/"
5071
--pre-js
51-
${CMAKE_CURRENT_SOURCE_DIR}/unittests.js
72+
${CMAKE_CURRENT_BINARY_DIR}/unittests_full.js
5273
-sASSERTIONS=2
5374
)
5475
set_target_properties(
@@ -57,9 +78,9 @@ set_target_properties(
5778
set_property(
5879
TARGET executorch_wasm_tests
5980
APPEND
60-
PROPERTY LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/unittests.js
81+
PROPERTY LINK_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/unittests_full.js
6182
)
6283
add_dependencies(
63-
executorch_wasm_tests executorch_wasm_test_models
84+
executorch_wasm_tests executorch_wasm_unittests executorch_wasm_test_models
6485
executorch_wasm_test_package_json
6586
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
describe("ETDump", () => {
10+
test("etdump enabled", () => {
11+
const module = et.Module.load("add_mul.pte");
12+
const inputs = [et.Tensor.ones([2, 2]), et.Tensor.ones([2, 2]), et.Tensor.ones([2, 2])];
13+
const output = module.forward(inputs);
14+
15+
inputs.forEach((input) => input.delete());
16+
output.forEach((output) => output.delete());
17+
const etdump = module.etdump();
18+
const buffer = etdump.buffer;
19+
expect(buffer).toBeInstanceOf(Uint8Array);
20+
expect(buffer.length).toBeGreaterThan(0);
21+
etdump.delete();
22+
module.delete();
23+
});
24+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
describe("ETDump", () => {
10+
test("etdump disabled", () => {
11+
const module = et.Module.load("add_mul.pte");
12+
expect(() => module.etdump()).toThrow();
13+
module.delete();
14+
});
15+
});

extension/wasm/wasm_bindings.cpp

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#include <executorch/runtime/core/exec_aten/util/tensor_util.h>
1515
#include <numeric>
1616

17+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
18+
#include <executorch/devtools/etdump/etdump_flatcc.h>
19+
#endif
20+
1721
#define THROW_JS_ERROR(errorType, message, ...) \
1822
({ \
1923
char msg_buf[256]; \
@@ -51,10 +55,15 @@ using executorch::aten::Tensor;
5155
using ::executorch::extension::BufferDataLoader;
5256
using ::executorch::runtime::Error;
5357
using ::executorch::runtime::EValue;
58+
using ::executorch::runtime::EventTracer;
5459
using ::executorch::runtime::Result;
5560
using ::executorch::runtime::Tag;
5661
using ::executorch::runtime::TensorInfo;
5762

63+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
64+
using executorch::etdump::ETDumpGen;
65+
#endif
66+
5867
namespace executorch {
5968
namespace extension {
6069
namespace wasm {
@@ -495,6 +504,35 @@ struct ET_EXPERIMENTAL JsMethodMeta {
495504
}
496505
};
497506

507+
/**
508+
* EXPERIMENTAL: Wrapper around ETDumpResult for JavaScript.
509+
*/
510+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
511+
class ET_EXPERIMENTAL JsETDumpResult final {
512+
public:
513+
JsETDumpResult() = delete;
514+
JsETDumpResult(const JsETDumpResult&) = delete;
515+
JsETDumpResult& operator=(const JsETDumpResult&) = delete;
516+
JsETDumpResult(JsETDumpResult&&) = default;
517+
JsETDumpResult& operator=(JsETDumpResult&&) = default;
518+
519+
explicit JsETDumpResult(uint8_t* buffer, size_t size)
520+
: buffer_(buffer), size_(size) {}
521+
522+
~JsETDumpResult() {
523+
free(buffer_);
524+
}
525+
526+
val get_buffer() const {
527+
return val(typed_memory_view(size_, buffer_));
528+
}
529+
530+
private:
531+
uint8_t* buffer_;
532+
size_t size_;
533+
};
534+
#endif
535+
498536
/**
499537
* EXPERIMENTAL: Wrapper around extension/Module for JavaScript.
500538
*/
@@ -518,17 +556,32 @@ class ET_EXPERIMENTAL JsModule final {
518556
val memory_view = val(typed_memory_view(length, buffer.data()));
519557
memory_view.call<void>("set", data);
520558
auto loader = std::make_unique<BufferDataLoader>(buffer.data(), length);
559+
560+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
561+
std::unique_ptr<EventTracer> etdump_gen = std::make_unique<ETDumpGen>();
562+
#else
563+
std::unique_ptr<EventTracer> etdump_gen = nullptr;
564+
#endif
521565
return std::make_unique<JsModule>(
522-
std::move(buffer), std::make_unique<Module>(std::move(loader)));
566+
std::move(buffer),
567+
std::make_unique<Module>(
568+
std::move(loader), nullptr, nullptr, std::move(etdump_gen)));
523569
}
524570

525571
static std::unique_ptr<JsModule> load(val data) {
526572
if (data.isNull() || data.isUndefined()) {
527573
THROW_JS_ERROR(TypeError, "Data cannot be null or undefined");
528574
}
529575
if (data.isString()) {
530-
return std::make_unique<JsModule>(
531-
std::make_unique<Module>(data.as<std::string>()));
576+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
577+
std::unique_ptr<EventTracer> etdump_gen = std::make_unique<ETDumpGen>();
578+
#else
579+
std::unique_ptr<EventTracer> etdump_gen = nullptr;
580+
#endif
581+
return std::make_unique<JsModule>(std::make_unique<Module>(
582+
data.as<std::string>(),
583+
Module::LoadMode::File,
584+
std::move(etdump_gen)));
532585
} else if (data.instanceof (val::global("Uint8Array"))) {
533586
return load_from_uint8_array(data);
534587
} else if (data.instanceof (val::global("ArrayBuffer"))) {
@@ -569,6 +622,18 @@ class ET_EXPERIMENTAL JsModule final {
569622
return JsMethodMeta::from_method_meta(res.get());
570623
}
571624

625+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
626+
std::unique_ptr<JsETDumpResult> etdump() {
627+
ETDumpGen* etdump_gen = dynamic_cast<ETDumpGen*>(module_->event_tracer());
628+
if (etdump_gen == nullptr) {
629+
return nullptr;
630+
}
631+
auto etdump_data = etdump_gen->get_etdump_data();
632+
return std::make_unique<JsETDumpResult>(
633+
static_cast<uint8_t*>(etdump_data.buf), etdump_data.size);
634+
}
635+
#endif
636+
572637
val_array<val> execute(const std::string& method, val js_inputs) {
573638
std::vector<EValue> inputs;
574639
if (js_inputs.isArray()) {
@@ -613,11 +678,19 @@ EMSCRIPTEN_BINDINGS(WasmBindings) {
613678
#define JS_DECLARE_TAG(NAME) .value(#NAME, Tag::NAME)
614679
EXECUTORCH_FORALL_TAGS(JS_DECLARE_TAG);
615680

681+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
682+
class_<JsETDumpResult>("ETDumpResult")
683+
.property("buffer", &JsETDumpResult::get_buffer);
684+
#endif
685+
616686
class_<JsModule>("Module")
617687
.class_function("load", &JsModule::load)
618688
.function("getMethods", &JsModule::get_methods)
619689
.function("loadMethod", &JsModule::load_method)
620690
.function("getMethodMeta", &JsModule::get_method_meta)
691+
#ifdef EXECUTORCH_ENABLE_EVENT_TRACER
692+
.function("etdump", &JsModule::etdump)
693+
#endif
621694
.function("execute", &JsModule::execute)
622695
.function("forward", &JsModule::forward);
623696
class_<JsTensor>("Tensor")

scripts/build_wasm_tests.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55
# This source code is licensed under the BSD-style license found in the
66
# LICENSE file in the root directory of this source tree.
77

8+
for arg in "$@"; do
9+
if [ "$arg" == "--enable-etdump" ]; then
10+
ETDUMP_OPTS="-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
11+
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
12+
-DFLATCC_ALLOW_WERROR=OFF"
13+
# FlatCC generates warnings depending on the compiler version.
14+
# This may be removed once the warnings are fixed.
15+
fi
16+
done
17+
818
CMAKE_OUT=cmake-out-wasm
919

1020
cd "$(dirname "${BASH_SOURCE[0]}")/../"
@@ -16,7 +26,7 @@ emcmake cmake . -DEXECUTORCH_BUILD_WASM=ON \
1626
-DEXECUTORCH_SELECT_OPS_LIST="aten::mm.out,aten::add.out" \
1727
-DEXECUTORCH_BUILD_TESTS=ON \
1828
-DCMAKE_BUILD_TYPE=Release \
19-
-B"${CMAKE_OUT}"
29+
${ETDUMP_OPTS} -B"${CMAKE_OUT}"
2030

2131
if [ "$(uname)" == "Darwin" ]; then
2232
CMAKE_JOBS=$(( $(sysctl -n hw.ncpu) - 1 ))

0 commit comments

Comments
 (0)