From 87a9c46fd67b2277d1833dc7be51b0ed093973a6 Mon Sep 17 00:00:00 2001 From: gasoonjia Date: Sun, 16 Feb 2025 00:34:57 -0800 Subject: [PATCH] [devtool] make ETDumpGen use bufferdatasink Pull Request resolved: https://github.com/pytorch/executorch/pull/8499 This diff enables customized debug data pipeline by making ETDumpGen leverage user-provided datasink. Details can be found in https://docs.google.com/document/d/1y_m32mKdj-OgLcLUz9TKhBW3PC3bBDYSBbeAH544EfM/edit?tab=t.0#heading=h.jlkcrurw482r ghstack-source-id: 266706035 @exported-using-ghexport Differential Revision: [D69647096](https://our.internmc.facebook.com/intern/diff/D69647096/) --- devtools/etdump/buffer_data_sink.h | 12 +- devtools/etdump/etdump_flatcc.cpp | 55 ++-- devtools/etdump/etdump_flatcc.h | 10 +- devtools/etdump/targets.bzl | 4 +- devtools/etdump/tests/etdump_test.cpp | 453 +++++++++++++++----------- 5 files changed, 308 insertions(+), 226 deletions(-) diff --git a/devtools/etdump/buffer_data_sink.h b/devtools/etdump/buffer_data_sink.h index e90e95c171c..4c84f93ffa2 100644 --- a/devtools/etdump/buffer_data_sink.h +++ b/devtools/etdump/buffer_data_sink.h @@ -25,7 +25,7 @@ namespace etdump { class BufferDataSink : public DataSinkBase { public: /** - * Constructs a BufferDataSink with a given buffer. + * Constructs a BufferDataSink with a given span buffer. * * @param[in] buffer A Span object representing the buffer where data will be * stored. @@ -33,11 +33,21 @@ class BufferDataSink : public DataSinkBase { explicit BufferDataSink(::executorch::runtime::Span buffer) : debug_buffer_(buffer), offset_(0) {} +/** + * Constructs a BufferDataSink with a given ptr to data blob, and the size of data blob. + * + * @param[in] ptr A pointer to the data blob where data will be stored. + * @param[in] size The size of the data blob in bytes. + */ + BufferDataSink(void* ptr, size_t size) + : debug_buffer_((uint8_t*)ptr, size), offset_(0) {} + BufferDataSink(const BufferDataSink&) = delete; BufferDataSink& operator=(const BufferDataSink&) = delete; BufferDataSink(BufferDataSink&&) = default; BufferDataSink& operator=(BufferDataSink&&) = default; + /** * Write data into the debug buffer and return the offset of the starting * location of the data within the buffer. diff --git a/devtools/etdump/etdump_flatcc.cpp b/devtools/etdump/etdump_flatcc.cpp index 24bbbfe88f6..632bc41709f 100644 --- a/devtools/etdump/etdump_flatcc.cpp +++ b/devtools/etdump/etdump_flatcc.cpp @@ -10,6 +10,7 @@ #include +#include #include #include #include @@ -28,6 +29,7 @@ using ::executorch::runtime::DebugHandle; using ::executorch::runtime::DelegateDebugIdType; using ::executorch::runtime::EValue; using ::executorch::runtime::EventTracerEntry; +using ::executorch::runtime::Result; using ::executorch::runtime::LoggedEValueType; using ::executorch::runtime::Span; using ::executorch::runtime::Tag; @@ -347,10 +349,10 @@ void ETDumpGen::log_intermediate_output_delegate_helper( ET_CHECK_MSG( (name == nullptr) ^ (delegate_debug_index == -1), "Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details."); - if (debug_buffer_.empty()) { - ET_CHECK_MSG(0, "Must pre-set debug buffer with set_debug_buffer()\n"); - return; - } + + ET_CHECK_MSG( + data_sink_, + "Must pre-set data sink before logging evalue with set_data_sink() or set_debug_buffer()\n"); check_ready_to_add_events(); int64_t string_id = name != nullptr ? create_string_entry(name) : -1; @@ -367,7 +369,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper( // Check the type of `output` then call the corresponding logging functions if constexpr (std::is_same::value) { - long offset = copy_tensor_to_debug_buffer(output); + long offset = write_tensor_or_raise_error(output); etdump_Tensor_ref_t tensor_ref = add_tensor_entry(builder_, output, offset); etdump_Value_start(builder_); @@ -377,7 +379,8 @@ void ETDumpGen::log_intermediate_output_delegate_helper( } else if constexpr (std::is_same>::value) { etdump_Tensor_vec_start(builder_); for (size_t i = 0; i < output.size(); ++i) { - long offset = copy_tensor_to_debug_buffer(output[i]); + + long offset = write_tensor_or_raise_error(output[i]); etdump_Tensor_vec_push( builder_, add_tensor_entry(builder_, output[i], offset)); } @@ -497,27 +500,15 @@ ETDumpResult ETDumpGen::get_etdump_data() { } void ETDumpGen::set_debug_buffer(Span buffer) { - debug_buffer_ = buffer; + data_sink_ = std::make_shared(buffer); } -size_t ETDumpGen::copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor) { - if (tensor.nbytes() == 0) { - return static_cast(-1); - } - uint8_t* offset_ptr = - internal::alignPointer(debug_buffer_.data() + debug_buffer_offset_, 64); - debug_buffer_offset_ = (offset_ptr - debug_buffer_.data()) + tensor.nbytes(); - ET_CHECK_MSG( - debug_buffer_offset_ <= debug_buffer_.size(), - "Ran out of space to store intermediate outputs."); - memcpy(offset_ptr, tensor.const_data_ptr(), tensor.nbytes()); - return (size_t)(offset_ptr - debug_buffer_.data()); +void ETDumpGen::set_data_sink(std::shared_ptr buffer_data_sink) { + data_sink_ = buffer_data_sink; } void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { - if (debug_buffer_.empty()) { - return; - } + ET_CHECK_MSG(data_sink_, "Must set data sink before logging evalue\n"); check_ready_to_add_events(); @@ -529,7 +520,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { switch (evalue.tag) { case Tag::Tensor: { executorch::aten::Tensor tensor = evalue.toTensor(); - long offset = copy_tensor_to_debug_buffer(tensor); + long offset = write_tensor_or_raise_error(tensor); etdump_Tensor_ref_t tensor_ref = add_tensor_entry(builder_, tensor, offset); @@ -551,7 +542,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { evalue.toTensorList(); etdump_Tensor_vec_start(builder_); for (size_t i = 0; i < tensors.size(); ++i) { - long offset = copy_tensor_to_debug_buffer(tensors[i]); + long offset = write_tensor_or_raise_error(tensors[i]); etdump_Tensor_vec_push( builder_, add_tensor_entry(builder_, tensors[i], offset)); } @@ -636,7 +627,21 @@ bool ETDumpGen::is_static_etdump() { } size_t ETDumpGen::get_debug_buffer_size() const { - return debug_buffer_.size(); + return ETDumpGen::get_data_sink_size(); +} + +size_t ETDumpGen::get_data_sink_size() const { + ET_CHECK_MSG(data_sink_, "Must set data sink before checking its size\n"); + Result ret = data_sink_->get_storage_size(); + ET_CHECK_MSG(ret.ok(), "Failed to get storage size with error 0x%" PRIx32, static_cast(ret.error())); + return ret.get(); +} + +long ETDumpGen::write_tensor_or_raise_error(Tensor tensor) { + ET_CHECK_MSG(data_sink_, "Must set data sink before writing data\n"); + Result ret = data_sink_->write(tensor.const_data_ptr(), tensor.nbytes()); + ET_CHECK_MSG(ret.ok(), "Failed to write tensor with error 0x%" PRIx32, static_cast(ret.error())); + return static_cast(ret.get()); } } // namespace etdump diff --git a/devtools/etdump/etdump_flatcc.h b/devtools/etdump/etdump_flatcc.h index d7781066533..37850f8a5d7 100644 --- a/devtools/etdump/etdump_flatcc.h +++ b/devtools/etdump/etdump_flatcc.h @@ -9,7 +9,9 @@ #pragma once #include +#include +#include #include #include #include @@ -141,8 +143,10 @@ class ETDumpGen : public ::executorch::runtime::EventTracer { ::executorch::runtime::DebugHandle delegate_debug_index, const double& output) override; void set_debug_buffer(::executorch::runtime::Span buffer); + void set_data_sink(std::shared_ptr buffer_data_sink); ETDumpResult get_etdump_data(); size_t get_debug_buffer_size() const; + size_t get_data_sink_size() const; size_t get_num_blocks(); bool is_static_etdump(); void reset(); @@ -158,7 +162,6 @@ class ETDumpGen : public ::executorch::runtime::EventTracer { void check_ready_to_add_events(); int64_t create_string_entry(const char* name); - size_t copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor); /** * Templated helper function used to log various types of intermediate output. @@ -170,10 +173,11 @@ class ETDumpGen : public ::executorch::runtime::EventTracer { ::executorch::runtime::DebugHandle delegate_debug_index, const T& output); + long write_tensor_or_raise_error(executorch::aten::Tensor tensor); + struct flatcc_builder* builder_; size_t num_blocks_ = 0; - ::executorch::runtime::Span debug_buffer_; - size_t debug_buffer_offset_ = 0; + std::shared_ptr data_sink_; int bundled_input_index_ = -1; State state_ = State::Init; struct internal::ETDumpStaticAllocator alloc_; diff --git a/devtools/etdump/targets.bzl b/devtools/etdump/targets.bzl index ef72ac7b37f..1a8f842ce03 100644 --- a/devtools/etdump/targets.bzl +++ b/devtools/etdump/targets.bzl @@ -117,7 +117,7 @@ def define_common_targets(): runtime.cxx_library( name = "buffer_data_sink" + aten_suffix, - headers = [ + exported_headers = [ "buffer_data_sink.h", ], srcs = [ @@ -153,6 +153,8 @@ def define_common_targets(): exported_deps = [ ":etdump_schema_flatcc", ":utils", + ":data_sink_base" + aten_suffix, + ":buffer_data_sink" + aten_suffix, "//executorch/runtime/core:event_tracer" + aten_suffix, "//executorch/runtime/core/exec_aten/util:scalar_type_util" + aten_suffix, ], diff --git a/devtools/etdump/tests/etdump_test.cpp b/devtools/etdump/tests/etdump_test.cpp index 664a5ee1a0d..a4336056c16 100644 --- a/devtools/etdump/tests/etdump_test.cpp +++ b/devtools/etdump/tests/etdump_test.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include using ::executorch::aten::ScalarType; using ::executorch::aten::Tensor; @@ -35,6 +35,8 @@ using ::executorch::runtime::Span; using ::executorch::runtime::Tag; using ::executorch::runtime::testing::TensorFactory; +using ::executorch::etdump::BufferDataSink; + class ProfilerETDumpTest : public ::testing::Test { protected: void SetUp() override { @@ -175,54 +177,78 @@ TEST_F(ProfilerETDumpTest, AllocationEvents) { TEST_F(ProfilerETDumpTest, DebugEvent) { for (size_t i = 0; i < 2; i++) { - TensorFactory tf; - EValue evalue(tf.ones({3, 2})); + for (size_t j = 0; j < 2; j++) { + TensorFactory tf; + EValue evalue(tf.ones({3, 2})); - etdump_gen[i]->create_event_block("test_block"); + etdump_gen[i]->create_event_block("test_block"); - void* ptr = malloc(2048); - Span buffer((uint8_t*)ptr, 2048); + void* ptr = malloc(2048); + Span buffer((uint8_t*)ptr, 2048); + ; + auto buffer_data_sink = std::make_shared(ptr, 2048); + + // using span to record debug data + if (j == 0) { + etdump_gen[i]->set_debug_buffer(buffer); + } + // using data sink to record debug data + else { + etdump_gen[i]->set_data_sink(buffer_data_sink); + } - etdump_gen[i]->set_debug_buffer(buffer); - etdump_gen[i]->log_evalue(evalue); - etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput); + etdump_gen[i]->log_evalue(evalue); + etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput); - EValue evalue_int((int64_t)5); - etdump_gen[i]->log_evalue(evalue_int); + EValue evalue_int((int64_t)5); + etdump_gen[i]->log_evalue(evalue_int); - EValue evalue_double((double)1.5); - etdump_gen[i]->log_evalue(evalue_double); + EValue evalue_double((double)1.5); + etdump_gen[i]->log_evalue(evalue_double); - EValue evalue_bool(true); - etdump_gen[i]->log_evalue(evalue_bool); + EValue evalue_bool(true); + etdump_gen[i]->log_evalue(evalue_bool); - etdump_gen[i]->log_evalue(evalue_bool); + etdump_gen[i]->log_evalue(evalue_bool); - free(ptr); + free(ptr); + } } } TEST_F(ProfilerETDumpTest, DebugEventTensorList) { for (size_t i = 0; i < 2; i++) { - TensorFactory tf; - executorch::aten::Tensor storage[2] = {tf.ones({3, 2}), tf.ones({3, 2})}; - EValue evalue_1(storage[0]); - EValue evalue_2(storage[1]); - EValue* values_p[2] = {&evalue_1, &evalue_2}; + for (size_t j = 0; j < 2; j++) { + TensorFactory tf; + executorch::aten::Tensor storage[2] = {tf.ones({3, 2}), tf.ones({3, 2})}; + EValue evalue_1(storage[0]); + EValue evalue_2(storage[1]); + EValue* values_p[2] = {&evalue_1, &evalue_2}; - BoxedEvalueList a_box(values_p, storage, 2); - EValue evalue(a_box); - evalue.tag = Tag::ListTensor; + BoxedEvalueList a_box(values_p, storage, 2); + EValue evalue(a_box); + evalue.tag = Tag::ListTensor; - etdump_gen[i]->create_event_block("test_block"); + etdump_gen[i]->create_event_block("test_block"); + + void* ptr = malloc(2048); + Span buffer((uint8_t*)ptr, 2048); + ; + auto buffer_data_sink = std::make_shared(ptr, 2048); - void* ptr = malloc(2048); - Span buffer((uint8_t*)ptr, 2048); + // using span to record debug data + if (j == 0) { + etdump_gen[i]->set_debug_buffer(buffer); + } + // using data sink to record debug data + else { + etdump_gen[i]->set_data_sink(buffer_data_sink); + } - etdump_gen[i]->set_debug_buffer(buffer); - etdump_gen[i]->log_evalue(evalue); + etdump_gen[i]->log_evalue(evalue); - free(ptr); + free(ptr); + } } } @@ -231,61 +257,73 @@ TEST_F(ProfilerETDumpTest, VerifyLogging) { EValue evalue(tf.ones({3, 2})); for (size_t i = 0; i < 2; i++) { - etdump_gen[i]->create_event_block("test_block"); + for (size_t j = 0; j < 2; j++) { + etdump_gen[i]->create_event_block("test_block"); - void* ptr = malloc(2048); - Span buffer((uint8_t*)ptr, 2048); + void* ptr = malloc(2048); + Span buffer((uint8_t*)ptr, 2048); + ; + auto buffer_data_sink = std::make_shared(ptr, 2048); - etdump_gen[i]->set_debug_buffer(buffer); - etdump_gen[i]->log_evalue(evalue); - etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput); + // using span to record debug data + if (j == 0) { + etdump_gen[i]->set_debug_buffer(buffer); + } + // using data sink to record debug data + else { + etdump_gen[i]->set_data_sink(buffer_data_sink); + } - ETDumpResult result = etdump_gen[i]->get_etdump_data(); - ASSERT_TRUE(result.buf != nullptr); - ASSERT_TRUE(result.size != 0); + etdump_gen[i]->log_evalue(evalue); + etdump_gen[i]->log_evalue(evalue, LoggedEValueType::kProgramOutput); - size_t size = 0; - void* buf = flatbuffers_read_size_prefix(result.buf, &size); - etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier( - buf, etdump_ETDump_file_identifier); + ETDumpResult result = etdump_gen[i]->get_etdump_data(); + ASSERT_TRUE(result.buf != nullptr); + ASSERT_TRUE(result.size != 0); - etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump); - ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1); - - etdump_Event_vec_t events = - etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0)); - ASSERT_EQ(etdump_Event_vec_len(events), 2); - - etdump_Event_table_t event = etdump_Event_vec_at(events, 0); - - etdump_DebugEvent_table_t single_debug_event = - etdump_Event_debug_event(event); - etdump_Value_table_t value = - etdump_DebugEvent_debug_entry(single_debug_event); - ASSERT_EQ(etdump_Value_tensor_is_present(value), true); - ASSERT_EQ(etdump_Value_output_is_present(value), false); - - etdump_Tensor_table_t tensor = etdump_Value_tensor(value); - executorch_flatbuffer_ScalarType_enum_t scalar_enum = - etdump_Tensor_scalar_type(tensor); - ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT); - flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor); - ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 2); - - event = etdump_Event_vec_at(events, 1); - single_debug_event = etdump_Event_debug_event(event); - value = etdump_DebugEvent_debug_entry(single_debug_event); - ASSERT_EQ(etdump_Value_tensor_is_present(value), true); - ASSERT_EQ(etdump_Value_output_is_present(value), true); - etdump_Bool_table_t bool_val = etdump_Value_output_get(value); - bool bool_val_from_table = etdump_Bool_bool_val(bool_val); - ASSERT_EQ(bool_val_from_table, true); - - free(ptr); - if (!etdump_gen[i]->is_static_etdump()) { - free(result.buf); + size_t size = 0; + void* buf = flatbuffers_read_size_prefix(result.buf, &size); + etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier( + buf, etdump_ETDump_file_identifier); + + etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump); + ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1); + + etdump_Event_vec_t events = + etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0)); + ASSERT_EQ(etdump_Event_vec_len(events), 2); + + etdump_Event_table_t event = etdump_Event_vec_at(events, 0); + + etdump_DebugEvent_table_t single_debug_event = + etdump_Event_debug_event(event); + etdump_Value_table_t value = + etdump_DebugEvent_debug_entry(single_debug_event); + ASSERT_EQ(etdump_Value_tensor_is_present(value), true); + ASSERT_EQ(etdump_Value_output_is_present(value), false); + + etdump_Tensor_table_t tensor = etdump_Value_tensor(value); + executorch_flatbuffer_ScalarType_enum_t scalar_enum = + etdump_Tensor_scalar_type(tensor); + ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT); + flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor); + ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 2); + + event = etdump_Event_vec_at(events, 1); + single_debug_event = etdump_Event_debug_event(event); + value = etdump_DebugEvent_debug_entry(single_debug_event); + ASSERT_EQ(etdump_Value_tensor_is_present(value), true); + ASSERT_EQ(etdump_Value_output_is_present(value), true); + etdump_Bool_table_t bool_val = etdump_Value_output_get(value); + bool bool_val_from_table = etdump_Bool_bool_val(bool_val); + ASSERT_EQ(bool_val_from_table, true); + + free(ptr); + if (!etdump_gen[i]->is_static_etdump()) { + free(result.buf); + } } } } @@ -432,58 +470,70 @@ TEST_F(ProfilerETDumpTest, VerifyData) { TEST_F(ProfilerETDumpTest, LogDelegateIntermediateOutput) { for (size_t i = 0; i < 2; i++) { - void* ptr = malloc(2048); - Span buffer((uint8_t*)ptr, 2048); - - etdump_gen[i]->create_event_block("test_block"); - TensorFactory tf; - - ET_EXPECT_DEATH( - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensor", - static_cast(-1), - tf.ones({3, 2})), - "Must pre-set debug buffer with set_debug_buffer()"); - etdump_gen[i]->set_debug_buffer(buffer); - - // Log a tensor - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensor", - static_cast(-1), - tf.ones({3, 2})); - - // Log a tensor list - std::vector tensors = {tf.ones({5, 4}), tf.ones({7, 6})}; - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensorlist", - static_cast(-1), - ArrayRef(tensors.data(), tensors.size())); + for (size_t j = 0; j < 2; j++) { + void* ptr = malloc(2048); + Span buffer((uint8_t*)ptr, 2048); - // Log an int - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensorlist", - static_cast(-1), - 10); + auto buffer_data_sink = std::make_shared(ptr, 2048); - // Log a double - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensorlist", - static_cast(-1), - 20.75); + etdump_gen[i]->create_event_block("test_block"); + TensorFactory tf; + + // using span to record debug data + if (j == 0) { + // TODO(gasoonjia): add similar ET_EXPECT_DEATH on BufferDataSink branch + ET_EXPECT_DEATH( + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensor", + static_cast(-1), + tf.ones({3, 2})), + "Must pre-set data sink before logging evalue with set_data_sink"); + etdump_gen[i]->set_debug_buffer(buffer); + } + // using data sink to record debug data + else { + etdump_gen[i]->set_data_sink(buffer_data_sink); + } - // Log a bool - etdump_gen[i]->log_intermediate_output_delegate( - "test_event_tensorlist", - static_cast(-1), - true); + // Log a tensor + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensor", + static_cast(-1), + tf.ones({3, 2})); + + // Log a tensor list + std::vector tensors = {tf.ones({5, 4}), tf.ones({7, 6})}; + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensorlist", + static_cast(-1), + ArrayRef(tensors.data(), tensors.size())); + + // Log an int + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensorlist", + static_cast(-1), + 10); + + // Log a double + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensorlist", + static_cast(-1), + 20.75); + + // Log a bool + etdump_gen[i]->log_intermediate_output_delegate( + "test_event_tensorlist", + static_cast(-1), + true); - ETDumpResult result = etdump_gen[i]->get_etdump_data(); - ASSERT_TRUE(result.buf != nullptr); - ASSERT_TRUE(result.size != 0); + ETDumpResult result = etdump_gen[i]->get_etdump_data(); + ASSERT_TRUE(result.buf != nullptr); + ASSERT_TRUE(result.size != 0); - free(ptr); - if (!etdump_gen[i]->is_static_etdump()) { - free(result.buf); + free(ptr); + if (!etdump_gen[i]->is_static_etdump()) { + free(result.buf); + } } } } @@ -493,81 +543,92 @@ TEST_F(ProfilerETDumpTest, VerifyDelegateIntermediateLogging) { EValue evalue(tf.ones({3, 2})); for (size_t i = 0; i < 2; i++) { - etdump_gen[i]->create_event_block("test_block"); - - void* ptr = malloc(2048); - Span buffer((uint8_t*)ptr, 2048); + for (size_t j = 0; j < 2; j++) { + etdump_gen[i]->create_event_block("test_block"); - etdump_gen[i]->set_debug_buffer(buffer); + void* ptr = malloc(2048); + Span buffer((uint8_t*)ptr, 2048); + ; + auto buffer_data_sink = std::make_shared(ptr, 2048); - // Event 0 - etdump_gen[i]->log_intermediate_output_delegate( - nullptr, 257, tf.ones({3, 4})); - // Event 1 - etdump_gen[i]->log_intermediate_output_delegate( - nullptr, 258, tf.ones({5, 6})); + // using span to record debug data + if (j == 0) { + etdump_gen[i]->set_debug_buffer(buffer); + } + // using data sink to record debug data + else { + etdump_gen[i]->set_data_sink(buffer_data_sink); + } - ETDumpResult result = etdump_gen[i]->get_etdump_data(); - ASSERT_TRUE(result.buf != nullptr); - ASSERT_TRUE(result.size != 0); + // Event 0 + etdump_gen[i]->log_intermediate_output_delegate( + nullptr, 257, tf.ones({3, 4})); + // Event 1 + etdump_gen[i]->log_intermediate_output_delegate( + nullptr, 258, tf.ones({5, 6})); - size_t size = 0; - void* buf = flatbuffers_read_size_prefix(result.buf, &size); - etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier( - buf, etdump_ETDump_file_identifier); + ETDumpResult result = etdump_gen[i]->get_etdump_data(); + ASSERT_TRUE(result.buf != nullptr); + ASSERT_TRUE(result.size != 0); - etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump); - ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1); - - etdump_Event_vec_t events = - etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0)); - ASSERT_EQ(etdump_Event_vec_len(events), 2); - - // Verify Event 0 - etdump_Event_table_t event_0 = etdump_Event_vec_at(events, 0); - - etdump_DebugEvent_table_t single_debug_event = - etdump_Event_debug_event(event_0); - etdump_Value_table_t value = - etdump_DebugEvent_debug_entry(single_debug_event); - ASSERT_EQ(etdump_Value_tensor_is_present(value), true); - - etdump_Tensor_table_t tensor = etdump_Value_tensor(value); - executorch_flatbuffer_ScalarType_enum_t scalar_enum = - etdump_Tensor_scalar_type(tensor); - ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT); - flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor); - ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 4); - - // Verify Event 1 - etdump_Event_table_t event_1 = etdump_Event_vec_at(events, 1); - - single_debug_event = etdump_Event_debug_event(event_1); - value = etdump_DebugEvent_debug_entry(single_debug_event); - - tensor = etdump_Value_tensor(value); - sizes = etdump_Tensor_sizes(tensor); - ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 5); - ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 6); - - // Event 1 should have a empty delegate_debug_id_str - flatbuffers_string_t delegate_debug_id_name = - etdump_DebugEvent_delegate_debug_id_str( - etdump_Event_debug_event(event_1)); + size_t size = 0; + void* buf = flatbuffers_read_size_prefix(result.buf, &size); + etdump_ETDump_table_t etdump = etdump_ETDump_as_root_with_identifier( + buf, etdump_ETDump_file_identifier); - EXPECT_EQ(delegate_debug_id_name, nullptr); - // Check for the correct delegate_debug_id_int - EXPECT_EQ( - etdump_DebugEvent_delegate_debug_id_int( - etdump_Event_debug_event(event_1)), - 258); + etdump_RunData_vec_t run_data_vec = etdump_ETDump_run_data(etdump); + ASSERT_EQ(etdump_RunData_vec_len(run_data_vec), 1); + + etdump_Event_vec_t events = + etdump_RunData_events(etdump_RunData_vec_at(run_data_vec, 0)); + ASSERT_EQ(etdump_Event_vec_len(events), 2); + + // Verify Event 0 + etdump_Event_table_t event_0 = etdump_Event_vec_at(events, 0); + + etdump_DebugEvent_table_t single_debug_event = + etdump_Event_debug_event(event_0); + etdump_Value_table_t value = + etdump_DebugEvent_debug_entry(single_debug_event); + ASSERT_EQ(etdump_Value_tensor_is_present(value), true); + + etdump_Tensor_table_t tensor = etdump_Value_tensor(value); + executorch_flatbuffer_ScalarType_enum_t scalar_enum = + etdump_Tensor_scalar_type(tensor); + ASSERT_EQ(scalar_enum, executorch_flatbuffer_ScalarType_FLOAT); + flatbuffers_int64_vec_t sizes = etdump_Tensor_sizes(tensor); + ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 3); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 4); + + // Verify Event 1 + etdump_Event_table_t event_1 = etdump_Event_vec_at(events, 1); + + single_debug_event = etdump_Event_debug_event(event_1); + value = etdump_DebugEvent_debug_entry(single_debug_event); + + tensor = etdump_Value_tensor(value); + sizes = etdump_Tensor_sizes(tensor); + ASSERT_EQ(flatbuffers_int64_vec_len(sizes), 2); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 0), 5); + ASSERT_EQ(flatbuffers_int64_vec_at(sizes, 1), 6); + + // Event 1 should have a empty delegate_debug_id_str + flatbuffers_string_t delegate_debug_id_name = + etdump_DebugEvent_delegate_debug_id_str( + etdump_Event_debug_event(event_1)); + + EXPECT_EQ(delegate_debug_id_name, nullptr); + // Check for the correct delegate_debug_id_int + EXPECT_EQ( + etdump_DebugEvent_delegate_debug_id_int( + etdump_Event_debug_event(event_1)), + 258); - free(ptr); - if (!etdump_gen[i]->is_static_etdump()) { - free(result.buf); + free(ptr); + if (!etdump_gen[i]->is_static_etdump()) { + free(result.buf); + } } } }