Skip to content

Commit 56c8dc2

Browse files
authored
etdumpfilter impl
Differential Revision: D72025517 Pull Request resolved: #9752
1 parent a55367b commit 56c8dc2

File tree

8 files changed

+354
-4
lines changed

8 files changed

+354
-4
lines changed

Diff for: devtools/etdump/etdump_filter.cpp

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+
#include <executorch/devtools/etdump/etdump_filter.h>
10+
11+
#include <executorch/runtime/core/error.h>
12+
13+
using ::executorch::runtime::DelegateDebugIntId;
14+
using ::executorch::runtime::Error;
15+
using ::executorch::runtime::kUnsetDelegateDebugIntId;
16+
17+
namespace executorch {
18+
namespace etdump {
19+
20+
ETDumpFilter::ETDumpFilter() = default;
21+
22+
Result<bool> ETDumpFilter::add_regex(string_view pattern) {
23+
auto regex = std::make_unique<re2::RE2>(pattern.data());
24+
if (!regex->ok()) {
25+
return Error::InvalidArgument; // Error during regex compilation
26+
}
27+
regex_patterns_.emplace_back(std::move(regex));
28+
return true;
29+
}
30+
31+
Result<bool> ETDumpFilter::set_debug_handle_range(size_t start, size_t end) {
32+
if (start >= end) {
33+
return Error::InvalidArgument; // Start is greater than end
34+
}
35+
if (start < 0 || end < 0) {
36+
return Error::InvalidArgument; // Start or end is negative
37+
}
38+
range_start_ = start;
39+
range_end_ = end;
40+
return true;
41+
}
42+
43+
Result<bool> ETDumpFilter::filter_name_(const char* name) {
44+
if (name == nullptr) {
45+
return Error::InvalidArgument;
46+
}
47+
if (regex_patterns_.empty()) {
48+
return true;
49+
}
50+
for (const auto& regex : regex_patterns_) {
51+
if (RE2::FullMatch(name, *regex)) {
52+
return true;
53+
}
54+
}
55+
return false;
56+
}
57+
58+
Result<bool> ETDumpFilter::filter_delegate_debug_index_(
59+
DelegateDebugIntId debug_handle) {
60+
if (debug_handle == kUnsetDelegateDebugIntId) {
61+
return Error::InvalidArgument; // Delegate debug index is unset
62+
}
63+
64+
if (range_start_ == 0 && range_end_ == 0) {
65+
return true;
66+
}
67+
68+
if (debug_handle < range_start_ || debug_handle >= range_end_) {
69+
return false;
70+
}
71+
72+
return true;
73+
}
74+
75+
Result<bool> ETDumpFilter::filter(
76+
const char* name,
77+
DelegateDebugIntId delegate_debug_index) {
78+
if ((name == nullptr) == (delegate_debug_index == kUnsetDelegateDebugIntId)) {
79+
return Error::InvalidArgument; // Name and delegate debug index should be
80+
// both set or unset
81+
}
82+
83+
if (name) {
84+
return filter_name_(name);
85+
} else {
86+
return filter_delegate_debug_index_(delegate_debug_index);
87+
}
88+
}
89+
90+
size_t ETDumpFilter::get_n_regex() const {
91+
return regex_patterns_.size();
92+
}
93+
94+
} // namespace etdump
95+
} // namespace executorch

Diff for: devtools/etdump/etdump_filter.h

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
#pragma once
10+
11+
#include <re2/re2.h>
12+
#include <memory>
13+
14+
#include <executorch/runtime/core/event_tracer.h>
15+
#include <executorch/runtime/core/result.h>
16+
#include <executorch/runtime/platform/platform.h>
17+
18+
namespace executorch::etdump {
19+
20+
using ::executorch::aten::string_view;
21+
using ::executorch::runtime::Result;
22+
23+
/**
24+
* ETDumpFilter is a class that filters intermediate output based on output's
25+
* name by full regex filtering, or delegate debug indices by range-based
26+
* filtering.
27+
*
28+
* Note that this filter supports up to MAX_REGEX_PATTERNS regex patterns with a
29+
* maximum length of MAX_PATTERN_LENGTH characters each.
30+
*/
31+
32+
class ETDumpFilter : public ::executorch::runtime::EventTracerFilterBase {
33+
public:
34+
ETDumpFilter();
35+
~ETDumpFilter() override = default;
36+
/**
37+
* Adds a regex pattern to the filter.
38+
*
39+
* @param[in] pattern A c string representing the regex pattern to be added.
40+
*
41+
* @return A Result<bool> indicating the success or failure of adding the
42+
* regex pattern.
43+
* - True if the pattern is successfully added.
44+
* - False if the pattern could not be added or if the maximum number
45+
* of patterns is exceeded.
46+
* - An error code if number of pattern has reached to cap, or any
47+
* error occurs during regex compilation.
48+
*/
49+
Result<bool> add_regex(string_view pattern);
50+
/**
51+
* Sets the range for the delegate debug index filtering as [start, end).
52+
* Note that this function will flush the existing range.
53+
*
54+
* @param[in] start The start of the range for filtering.
55+
* @param[in] end The end of the range for filtering.
56+
*
57+
* @return A Result<bool> indicating the success or failure of setting the
58+
* range.
59+
* - True if the range is successfully set.
60+
* - An error code if an error occurs.
61+
*/
62+
Result<bool> set_debug_handle_range(size_t start, size_t end);
63+
64+
/**
65+
* Filters events based on the given name or delegate debug index.
66+
*
67+
* Note that everytime only one of either the name or delegate_debug_index
68+
* should be passed in.
69+
*
70+
* @param[in] name A pointer to a string representing the `name` of the
71+
* event. If `delegate_debug_index` is not set to kUnsetDebugHandle, `name`
72+
* should be set to nullptr.
73+
*
74+
* @param[in] delegate_debug_index A DebugHandle representing the debug index
75+
* of the delegate. If `name` is not nullptr, this should be set to
76+
* kUnsetDebugHandle.
77+
*
78+
* @return A Result<bool> indicating whether the event matches the filter
79+
* criteria.
80+
* - True if the event matches the filter, or filter is unset.
81+
* - False if the event does not match or is unknown.
82+
* - An error code if an error occurs during filtering.
83+
*/
84+
Result<bool> filter(
85+
const char* name,
86+
::executorch::runtime::DelegateDebugIntId delegate_debug_index) override;
87+
88+
/**
89+
* Returns the number of regex patterns in the filter.
90+
*/
91+
size_t get_n_regex() const;
92+
93+
private:
94+
std::vector<std::unique_ptr<re2::RE2>> regex_patterns_;
95+
size_t range_start_ = 0;
96+
size_t range_end_ = 0;
97+
Result<bool> filter_name_(const char* name);
98+
Result<bool> filter_delegate_debug_index_(
99+
::executorch::runtime::DelegateDebugIntId delegate_debug_index);
100+
};
101+
102+
} // namespace executorch::etdump

Diff for: devtools/etdump/etdump_flatcc.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <executorch/devtools/etdump/etdump_schema_flatcc_builder.h>
1616
#include <executorch/devtools/etdump/etdump_schema_flatcc_reader.h>
1717
#include <executorch/devtools/etdump/utils.h>
18+
#include <executorch/runtime/core/error.h>
1819
#include <executorch/runtime/core/exec_aten/exec_aten.h>
1920
#include <executorch/runtime/core/exec_aten/util/scalar_type_util.h>
2021
#include <executorch/runtime/platform/assert.h>
@@ -28,6 +29,7 @@ using ::executorch::runtime::ChainID;
2829
using ::executorch::runtime::DebugHandle;
2930
using ::executorch::runtime::DelegateDebugIdType;
3031
using ::executorch::runtime::DelegateDebugIntId;
32+
using ::executorch::runtime::Error;
3133
using ::executorch::runtime::EValue;
3234
using ::executorch::runtime::EventTracerEntry;
3335
using ::executorch::runtime::kUnsetDelegateDebugIntId;

Diff for: devtools/etdump/etdump_flatcc.h

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#pragma once
1010

1111
#include <cstdint>
12-
#include <memory>
1312

1413
#include <executorch/devtools/etdump/data_sinks/buffer_data_sink.h>
1514
#include <executorch/devtools/etdump/data_sinks/data_sink_base.h>

Diff for: devtools/etdump/targets.bzl

+21
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,27 @@ def define_common_targets():
101101
for aten_mode in get_aten_mode_options():
102102
aten_suffix = "_aten" if aten_mode else ""
103103

104+
runtime.cxx_library(
105+
name = "etdump_filter" + aten_suffix,
106+
srcs = [
107+
"etdump_filter.cpp",
108+
],
109+
exported_headers = [
110+
"etdump_filter.h",
111+
],
112+
deps = [
113+
"//executorch/runtime/platform:platform",
114+
],
115+
exported_deps = [
116+
"fbsource//third-party/re2:re2",
117+
"//executorch/runtime/core:event_tracer" + aten_suffix,
118+
],
119+
visibility = [
120+
"//executorch/...",
121+
"@EXECUTORCH_CLIENTS",
122+
],
123+
)
124+
104125
runtime.cxx_library(
105126
name = "etdump_flatcc" + aten_suffix,
106127
srcs = [

Diff for: devtools/etdump/tests/etdump_filter_test.cpp

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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+
#include <gtest/gtest.h>
10+
11+
#include <executorch/devtools/etdump/etdump_filter.h>
12+
#include <executorch/runtime/platform/runtime.h>
13+
14+
#include <cstring>
15+
16+
using ::executorch::etdump::ETDumpFilter;
17+
using ::executorch::runtime::Error;
18+
using ::executorch::runtime::kUnsetDelegateDebugIntId;
19+
using ::executorch::runtime::Result;
20+
21+
class ETDumpFilterTest : public ::testing::Test {
22+
protected:
23+
ETDumpFilter filter;
24+
25+
void SetUp() override {
26+
torch::executor::runtime_init();
27+
}
28+
29+
void TearDown() override {}
30+
};
31+
32+
TEST_F(ETDumpFilterTest, AddRegexPatternSuccess) {
33+
Result<bool> result = filter.add_regex("test.*");
34+
EXPECT_TRUE(result.ok());
35+
EXPECT_TRUE(result.get());
36+
}
37+
38+
TEST_F(ETDumpFilterTest, SetDebugHandleRangeSuccess) {
39+
Result<bool> result = filter.set_debug_handle_range(10, 20);
40+
EXPECT_TRUE(result.ok());
41+
EXPECT_TRUE(result.get());
42+
}
43+
44+
TEST_F(ETDumpFilterTest, SetDebugHandleRangeFailure) {
45+
Result<bool> result = filter.set_debug_handle_range(20, 10);
46+
EXPECT_EQ(result.error(), Error::InvalidArgument);
47+
}
48+
49+
TEST_F(ETDumpFilterTest, FilterByNameSuccess) {
50+
filter.add_regex("event.*");
51+
Result<bool> result = filter.filter("event_name", kUnsetDelegateDebugIntId);
52+
EXPECT_TRUE(result.ok());
53+
EXPECT_TRUE(result.get());
54+
}
55+
56+
TEST_F(ETDumpFilterTest, PartialMatchingFailed) {
57+
filter.add_regex("event.*");
58+
Result<bool> result =
59+
filter.filter("non_matching_event", kUnsetDelegateDebugIntId);
60+
EXPECT_TRUE(result.ok());
61+
EXPECT_FALSE(result.get());
62+
}
63+
64+
TEST_F(ETDumpFilterTest, FilterByDelegateDebugIndexSuccess) {
65+
filter.set_debug_handle_range(10, 20);
66+
Result<bool> result = filter.filter(nullptr, 15);
67+
EXPECT_TRUE(result.ok());
68+
EXPECT_TRUE(result.get());
69+
}
70+
71+
TEST_F(ETDumpFilterTest, FilterByDelegateDebugIndexFailure) {
72+
filter.set_debug_handle_range(10, 20);
73+
Result<bool> result = filter.filter(nullptr, 25);
74+
EXPECT_TRUE(result.ok());
75+
EXPECT_FALSE(result.get());
76+
}
77+
78+
TEST_F(ETDumpFilterTest, NaiveFilterNameInputCanSucceed) {
79+
Result<bool> result = filter.filter("any_input", kUnsetDelegateDebugIntId);
80+
EXPECT_TRUE(result.ok());
81+
EXPECT_TRUE(result.get());
82+
}
83+
84+
TEST_F(ETDumpFilterTest, NaiveFilterDebugHandleInputCanSucceed) {
85+
Result<bool> result = filter.filter(nullptr, 12345);
86+
EXPECT_TRUE(result.ok());
87+
EXPECT_TRUE(result.get());
88+
}
89+
90+
TEST_F(ETDumpFilterTest, IllegalInput) {
91+
filter.add_regex("pattern");
92+
Result<bool> result = filter.filter("matching_event", 1);
93+
EXPECT_EQ(result.error(), Error::InvalidArgument);
94+
}
95+
96+
TEST_F(ETDumpFilterTest, NoMatchFirstThenMatch) {
97+
filter.add_regex("non_matching_pattern");
98+
Result<bool> result_1 =
99+
filter.filter("matching_event", kUnsetDelegateDebugIntId);
100+
EXPECT_TRUE(result_1.ok());
101+
EXPECT_FALSE(result_1.get());
102+
filter.add_regex("matching_.*");
103+
Result<bool> result_2 =
104+
filter.filter("matching_event", kUnsetDelegateDebugIntId);
105+
EXPECT_TRUE(result_2.ok());
106+
EXPECT_TRUE(result_2.get());
107+
}
108+
109+
TEST_F(ETDumpFilterTest, MatchRegexFirstThen) {
110+
filter.add_regex("matching.*");
111+
Result<bool> result_1 =
112+
filter.filter("matching_event", kUnsetDelegateDebugIntId);
113+
EXPECT_TRUE(result_1.ok());
114+
EXPECT_TRUE(result_1.get());
115+
filter.add_regex("non_matching_pattern");
116+
Result<bool> result_2 =
117+
filter.filter("matching_event", kUnsetDelegateDebugIntId);
118+
EXPECT_TRUE(result_2.ok());
119+
EXPECT_TRUE(result_2.get());
120+
}

Diff for: devtools/etdump/tests/targets.bzl

+11
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,14 @@ def define_common_targets():
2121
"//executorch/runtime/core/exec_aten/testing_util:tensor_util",
2222
],
2323
)
24+
25+
runtime.cxx_test(
26+
name = "etdump_filter_test",
27+
srcs = [
28+
"etdump_filter_test.cpp",
29+
],
30+
deps = [
31+
"//executorch/devtools/etdump:etdump_filter",
32+
"//executorch/runtime/platform:platform",
33+
],
34+
)

0 commit comments

Comments
 (0)