Skip to content

Commit 5da4e5e

Browse files
committed
Update on "[devtool] introduce datasink class to etdump"
this diff introduce datasink class, the class for managing the customized debug data storage pipeline. Detials can be found in https://docs.google.com/document/d/1y_m32mKdj-OgLcLUz9TKhBW3PC3bBDYSBbeAH544EfM/edit?tab=t.0 Differential Revision: [D69583422](https://our.internmc.facebook.com/intern/diff/D69583422/) [ghstack-poisoned]
2 parents 9597b5f + f37c5a1 commit 5da4e5e

File tree

7 files changed

+113
-66
lines changed

7 files changed

+113
-66
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
2+
3+
#include <executorch/devtools/etdump/buffer_data_sink.h>
4+
#include <executorch/devtools/etdump/utils.h>
5+
6+
namespace executorch {
7+
namespace etdump {
8+
9+
Result<size_t> BufferDataSink::write(const void* ptr, size_t length) {
10+
if (length == 0) {
11+
return static_cast<size_t>(-1);
12+
}
13+
uint8_t* offset_ptr =
14+
internal::alignPointer(debug_buffer_.data() + offset_, 64);
15+
16+
// Zero out the padding between data blobs.
17+
size_t n_zero_pad = offset_ptr - debug_buffer_.data() - offset_;
18+
memset(debug_buffer_.data() + offset_, 0, n_zero_pad);
19+
20+
offset_ = (offset_ptr - debug_buffer_.data()) + length;
21+
ET_CHECK_MSG(
22+
offset_ <= debug_buffer_.size(),
23+
"Ran out of space to store tensor data.");
24+
memcpy(offset_ptr, ptr, length);
25+
return (size_t)(offset_ptr - debug_buffer_.data());
26+
}
27+
28+
Result<size_t> BufferDataSink::write_tensor(
29+
const executorch::aten::Tensor& tensor) {
30+
return write(tensor.const_data_ptr(), tensor.nbytes());
31+
}
32+
33+
Result<size_t> BufferDataSink::get_storage_size() const {
34+
return debug_buffer_.size();
35+
}
36+
37+
size_t BufferDataSink::get_used_bytes() const {
38+
return offset_;
39+
}
40+
41+
} // namespace etdump
42+
} // namespace executorch

devtools/etdump/data_sink.h renamed to devtools/etdump/buffer_data_sink.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
namespace executorch {
1010
namespace etdump {
1111

12-
class DataSink : public DataSinkBase {
12+
class BufferDataSink : public DataSinkBase {
1313
public:
14-
explicit DataSink(::executorch::runtime::Span<uint8_t> buffer)
14+
explicit BufferDataSink(::executorch::runtime::Span<uint8_t> buffer)
1515
: debug_buffer_(buffer), offset_(0) {}
1616

17-
size_t write_tensor(const executorch::aten::Tensor& tensor) override;
18-
size_t get_storage_size() const override;
17+
Result<size_t> write(const void* ptr, size_t length) override;
18+
Result<size_t> write_tensor(const executorch::aten::Tensor& tensor);
19+
Result<size_t> get_storage_size() const override;
1920
size_t get_used_bytes() const override;
2021

2122
private:

devtools/etdump/data_sink.cpp

Lines changed: 0 additions & 32 deletions
This file was deleted.

devtools/etdump/data_sink_base.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
#pragma once
44

55
#include <executorch/runtime/core/exec_aten/exec_aten.h>
6-
#include <cstdlib>
6+
#include <executorch/runtime/core/result.h>
7+
8+
using ::executorch::runtime::Result;
79

810
namespace executorch {
911
namespace etdump {
1012

1113
/**
1214
* DataSinkBase is an abstract class that users can inherit and implement
1315
* to customize the storage and management of debug data in ETDumpGen. This
14-
* class provides an basic and essential interface for writing tensor data to a
16+
* class provides an basic and essential interface for writing datablob to a
1517
* user-defined storage, retrieving storage capacity, and tracking the amount of
1618
* data stored.
1719
*/
@@ -22,21 +24,24 @@ class DataSinkBase {
2224
*/
2325
virtual ~DataSinkBase() = default;
2426
/**
25-
* Write tensor data into the debug storage. This method should be implemented
27+
* Write data into the debug storage. This method should be implemented
2628
* by derived classes to handle the specifics of data storage.
2729
*
28-
* @param[in] tensor The tensor data to be written into the storage.
29-
* @return The offset of the starting location of the tensor data within the
30-
* debug storage, which will be recorded in corresponding tensor
31-
* metadata of ETDump.
30+
* @param[in] ptr A pointer to the data to be written into the storage.
31+
* @param[in] length The size of the data in bytes.
32+
* @return The offset of the starting location of the data within the
33+
* debug storage, which will be recorded in the corresponding
34+
* metadata of ETDump.
3235
*/
33-
virtual size_t write_tensor(const executorch::aten::Tensor& tensor) = 0;
36+
virtual Result<size_t> write(const void* ptr, size_t length) = 0;
3437
/**
3538
* Get the maximum capacity of the debug storage in bytes.
39+
* Should return Error::NotSupported if the capacity is not available
40+
* (e.g. unbounded storage like internet or file)
3641
*
3742
* @return The total size of the debug storage.
3843
*/
39-
virtual size_t get_storage_size() const = 0;
44+
virtual Result<size_t> get_storage_size() const = 0;
4045
/**
4146
* Get the number of bytes currently used in the debug storage.
4247
*

devtools/etdump/targets.bzl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ def define_common_targets():
116116
)
117117

118118
runtime.cxx_library(
119-
name = "data_sink" + aten_suffix,
119+
name = "buffer_data_sink" + aten_suffix,
120120
headers = [
121-
"data_sink.h",
121+
"buffer_data_sink.h",
122122
],
123123
srcs = [
124-
"data_sink.cpp",
124+
"buffer_data_sink.cpp",
125125
],
126126
deps = [
127127
":utils",
@@ -149,7 +149,6 @@ def define_common_targets():
149149
],
150150
deps = [
151151
"//executorch/runtime/platform:platform",
152-
":utils",
153152
],
154153
exported_deps = [
155154
":etdump_schema_flatcc",

devtools/etdump/tests/data_sink_test.cpp renamed to devtools/etdump/tests/buffer_data_sink_test.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
#include <executorch/devtools/etdump/data_sink.h>
9+
#include <executorch/devtools/etdump/buffer_data_sink.h>
1010
#include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
1111
#include <executorch/runtime/core/span.h>
1212
#include <executorch/runtime/platform/runtime.h>
@@ -19,15 +19,15 @@ using executorch::aten::Tensor;
1919
using ::executorch::runtime::Span;
2020
using torch::executor::testing::TensorFactory;
2121

22-
class DataSinkTest : public ::testing::Test {
22+
class BufferDataSinkTest : public ::testing::Test {
2323
protected:
2424
void SetUp() override {
2525
torch::executor::runtime_init();
2626
// Allocate a small buffer for testing
2727
buffer_size_ = 128; // Small size for testing
2828
buffer_ptr_ = malloc(buffer_size_);
2929
buffer_ = Span<uint8_t>(static_cast<uint8_t*>(buffer_ptr_), buffer_size_);
30-
data_sink_ = std::make_unique<executorch::etdump::DataSink>(buffer_);
30+
data_sink_ = std::make_unique<executorch::etdump::BufferDataSink>(buffer_);
3131
}
3232

3333
void TearDown() override {
@@ -37,18 +37,35 @@ class DataSinkTest : public ::testing::Test {
3737
size_t buffer_size_;
3838
void* buffer_ptr_;
3939
Span<uint8_t> buffer_;
40-
std::unique_ptr<executorch::etdump::DataSink> data_sink_;
40+
std::unique_ptr<executorch::etdump::BufferDataSink> data_sink_;
4141
};
4242

43-
TEST_F(DataSinkTest, StorageSizeCheck) {
44-
EXPECT_EQ(data_sink_->get_storage_size(), buffer_size_);
43+
TEST_F(BufferDataSinkTest, StorageSizeCheck) {
44+
Result<size_t> ret = data_sink_->get_storage_size();
45+
if (!ret.ok()) {
46+
ET_LOG(
47+
Info,
48+
"Get storage size failed with 0x%" PRIx32,
49+
(unsigned int)ret.error());
50+
}
51+
size_t storage_size = ret.get();
52+
EXPECT_EQ(storage_size, buffer_size_);
4553
}
4654

47-
TEST_F(DataSinkTest, WriteOneTensorAndCheckData) {
55+
TEST_F(BufferDataSinkTest, WriteOneTensorAndCheckData) {
4856
TensorFactory<ScalarType::Float> tf;
4957
Tensor tensor = tf.make({1, 4}, {1.0, 2.0, 3.0, 4.0});
5058

51-
size_t offset = data_sink_->write_tensor(tensor);
59+
Result<size_t> ret = data_sink_->write_tensor(tensor);
60+
if (!ret.ok()) {
61+
ET_LOG(
62+
Info,
63+
"Write tensor into debug storage failed with 0x%" PRIx32,
64+
(unsigned int)ret.error());
65+
}
66+
67+
size_t offset = ret.get();
68+
5269
EXPECT_NE(offset, static_cast<size_t>(-1));
5370

5471
// Check that the data in the buffer matches the tensor data
@@ -59,14 +76,21 @@ TEST_F(DataSinkTest, WriteOneTensorAndCheckData) {
5976
}
6077
}
6178

62-
TEST_F(DataSinkTest, WriteMultiTensorsAndCheckData) {
79+
TEST_F(BufferDataSinkTest, WriteMultiTensorsAndCheckData) {
6380
TensorFactory<ScalarType::Float> tf;
6481
std::vector<Tensor> tensors = {
6582
tf.make({1, 4}, {1.0, 2.0, 3.0, 4.0}),
6683
tf.make({1, 4}, {5.0, 6.0, 7.0, 8.0})};
67-
size_t offset = 0;
6884
for (const auto& tensor : tensors) {
69-
offset = data_sink_->write_tensor(tensor);
85+
Result<size_t> ret = data_sink_->write_tensor(tensor);
86+
if (!ret.ok()) {
87+
ET_LOG(
88+
Info,
89+
"Write tensor into debug storage failed with 0x%" PRIx32,
90+
(unsigned int)ret.error());
91+
}
92+
93+
size_t offset = ret.get();
7094
EXPECT_NE(offset, static_cast<size_t>(-1));
7195
// Check that the data in the buffer matches the tensor data
7296
const float* buffer_data =
@@ -77,17 +101,25 @@ TEST_F(DataSinkTest, WriteMultiTensorsAndCheckData) {
77101
}
78102
}
79103

80-
TEST_F(DataSinkTest, PointerAlignmentCheck) {
104+
TEST_F(BufferDataSinkTest, PointerAlignmentCheck) {
81105
TensorFactory<ScalarType::Float> tf;
82106
Tensor tensor = tf.make({1, 4}, {1.0, 2.0, 3.0, 4.0});
83-
size_t offset = data_sink_->write_tensor(tensor);
107+
Result<size_t> ret = data_sink_->write_tensor(tensor);
108+
if (!ret.ok()) {
109+
ET_LOG(
110+
Info,
111+
"Write tensor into debug storage failed with 0x%" PRIx32,
112+
(unsigned int)ret.error());
113+
}
114+
115+
size_t offset = ret.get();
84116
EXPECT_NE(offset, static_cast<size_t>(-1));
85117
// Check that the offset pointer is 64-byte aligned
86118
const uint8_t* offset_ptr = buffer_.data() + offset;
87119
EXPECT_EQ(reinterpret_cast<uintptr_t>(offset_ptr) % 64, 0);
88120
}
89121

90-
TEST_F(DataSinkTest, WriteUntilOverflow) {
122+
TEST_F(BufferDataSinkTest, WriteUntilOverflow) {
91123
TensorFactory<ScalarType::Float> tf;
92124
Tensor tensor = tf.zeros({1, 8}); // Large tensor to fill the buffer
93125

devtools/etdump/tests/targets.bzl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ def define_common_targets():
2121
)
2222

2323
runtime.cxx_test(
24-
name = "data_sink_test",
24+
name = "buffer_data_sink_test",
2525
srcs = [
26-
"data_sink_test.cpp",
26+
"buffer_data_sink_test.cpp",
2727
],
2828
deps = [
29-
"//executorch/devtools/etdump:data_sink",
29+
"//executorch/devtools/etdump:buffer_data_sink",
3030
"//executorch/runtime/core/exec_aten/testing_util:tensor_util",
3131
],
3232
)

0 commit comments

Comments
 (0)