1010
1111#include < cstring>
1212
13+ #include < executorch/devtools/etdump/buffer_data_sink.h>
1314#include < executorch/devtools/etdump/emitter.h>
1415#include < executorch/devtools/etdump/etdump_schema_flatcc_builder.h>
1516#include < executorch/devtools/etdump/etdump_schema_flatcc_reader.h>
@@ -29,6 +30,7 @@ using ::executorch::runtime::DelegateDebugIdType;
2930using ::executorch::runtime::EValue;
3031using ::executorch::runtime::EventTracerEntry;
3132using ::executorch::runtime::LoggedEValueType;
33+ using ::executorch::runtime::Result;
3234using ::executorch::runtime::Span;
3335using ::executorch::runtime::Tag;
3436
@@ -142,6 +144,7 @@ ETDumpGen::~ETDumpGen() {
142144void ETDumpGen::reset () {
143145 state_ = State::Init;
144146 num_blocks_ = 0 ;
147+ data_sink_ = nullptr ;
145148 flatcc_builder_reset (builder_);
146149 flatbuffers_buffer_start (builder_, etdump_ETDump_file_identifier);
147150 etdump_ETDump_start_as_root_with_size (builder_);
@@ -347,10 +350,10 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
347350 ET_CHECK_MSG (
348351 (name == nullptr ) ^ (delegate_debug_index == -1 ),
349352 " Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details." );
350- if (debug_buffer_. empty ()) {
351- ET_CHECK_MSG (0 , " Must pre-set debug buffer with set_debug_buffer() \n " );
352- return ;
353- }
353+
354+ ET_CHECK_MSG (
355+ data_sink_,
356+ " Must pre-set data sink before logging evalue with set_data_sink() or set_debug_buffer() \n " );
354357
355358 check_ready_to_add_events ();
356359 int64_t string_id = name != nullptr ? create_string_entry (name) : -1 ;
@@ -367,7 +370,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
367370
368371 // Check the type of `output` then call the corresponding logging functions
369372 if constexpr (std::is_same<T, Tensor>::value) {
370- long offset = copy_tensor_to_debug_buffer (output);
373+ long offset = write_tensor_or_raise_error (output);
371374 etdump_Tensor_ref_t tensor_ref = add_tensor_entry (builder_, output, offset);
372375
373376 etdump_Value_start (builder_);
@@ -377,7 +380,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
377380 } else if constexpr (std::is_same<T, ArrayRef<Tensor>>::value) {
378381 etdump_Tensor_vec_start (builder_);
379382 for (size_t i = 0 ; i < output.size (); ++i) {
380- long offset = copy_tensor_to_debug_buffer (output[i]);
383+ long offset = write_tensor_or_raise_error (output[i]);
381384 etdump_Tensor_vec_push (
382385 builder_, add_tensor_entry (builder_, output[i], offset));
383386 }
@@ -497,27 +500,22 @@ ETDumpResult ETDumpGen::get_etdump_data() {
497500}
498501
499502void ETDumpGen::set_debug_buffer (Span<uint8_t > buffer) {
500- debug_buffer_ = buffer;
503+ Result<BufferDataSink> bds_ret = BufferDataSink::create (buffer);
504+ ET_CHECK_MSG (
505+ bds_ret.ok (),
506+ " Failed to write tensor with error 0x%" PRIx32,
507+ static_cast <uint32_t >(bds_ret.error ()));
508+
509+ buffer_data_sink_ = std::move (bds_ret.get ());
510+ data_sink_ = &buffer_data_sink_;
501511}
502512
503- size_t ETDumpGen::copy_tensor_to_debug_buffer (executorch::aten::Tensor tensor) {
504- if (tensor.nbytes () == 0 ) {
505- return static_cast <size_t >(-1 );
506- }
507- uint8_t * offset_ptr =
508- internal::align_pointer (debug_buffer_.data () + debug_buffer_offset_, 64 );
509- debug_buffer_offset_ = (offset_ptr - debug_buffer_.data ()) + tensor.nbytes ();
510- ET_CHECK_MSG (
511- debug_buffer_offset_ <= debug_buffer_.size (),
512- " Ran out of space to store intermediate outputs." );
513- memcpy (offset_ptr, tensor.const_data_ptr (), tensor.nbytes ());
514- return (size_t )(offset_ptr - debug_buffer_.data ());
513+ void ETDumpGen::set_data_sink (DataSinkBase* data_sink) {
514+ data_sink_ = data_sink;
515515}
516516
517517void ETDumpGen::log_evalue (const EValue& evalue, LoggedEValueType evalue_type) {
518- if (debug_buffer_.empty ()) {
519- return ;
520- }
518+ ET_CHECK_MSG (data_sink_, " Must set data sink before logging evalue\n " );
521519
522520 check_ready_to_add_events ();
523521
@@ -529,7 +527,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) {
529527 switch (evalue.tag ) {
530528 case Tag::Tensor: {
531529 executorch::aten::Tensor tensor = evalue.toTensor ();
532- long offset = copy_tensor_to_debug_buffer (tensor);
530+ long offset = write_tensor_or_raise_error (tensor);
533531 etdump_Tensor_ref_t tensor_ref =
534532 add_tensor_entry (builder_, tensor, offset);
535533
@@ -551,7 +549,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) {
551549 evalue.toTensorList ();
552550 etdump_Tensor_vec_start (builder_);
553551 for (size_t i = 0 ; i < tensors.size (); ++i) {
554- long offset = copy_tensor_to_debug_buffer (tensors[i]);
552+ long offset = write_tensor_or_raise_error (tensors[i]);
555553 etdump_Tensor_vec_push (
556554 builder_, add_tensor_entry (builder_, tensors[i], offset));
557555 }
@@ -635,8 +633,31 @@ bool ETDumpGen::is_static_etdump() {
635633 return alloc_.data != nullptr ;
636634}
637635
638- size_t ETDumpGen::get_debug_buffer_size () const {
639- return debug_buffer_.size ();
636+ DataSinkBase* ETDumpGen::get_data_sink () {
637+ return data_sink_;
638+ }
639+
640+ long ETDumpGen::write_tensor_or_raise_error (Tensor tensor) {
641+ // Previously, the function copy_tensor_to_debug_buffer returned 0xFF..F when
642+ // given an empty tensor, which is an invalid offset for most buffers. In our
643+ // data sink, we will return the current debug_buffer_offset for better
644+ // clarity. We are isolating the empty tensor case here using the old logic to
645+ // avoid any backward compatibility issues while introducing the data sink.
646+ // Once the data sink is fully implemented, we can remove this check and apply
647+ // the new logic to all cases.
648+ // TODO(gasoonjia): remove this check after datasink is fully rolled out.
649+ if (tensor.nbytes () == 0 ) {
650+ return static_cast <size_t >(-1 );
651+ }
652+
653+ ET_CHECK_MSG (data_sink_, " Must set data sink before writing data" );
654+ Result<size_t > ret =
655+ data_sink_->write (tensor.const_data_ptr (), tensor.nbytes ());
656+ ET_CHECK_MSG (
657+ ret.ok (),
658+ " Failed to write tensor with error 0x%" PRIx32,
659+ static_cast <uint32_t >(ret.error ()));
660+ return static_cast <long >(ret.get ());
640661}
641662
642663} // namespace etdump
0 commit comments