Skip to content

Commit c14e7d6

Browse files
committed
DPL: speedup DataDescriptorMatcher
Previous results: BM_MatchedSingleQuery 99 ns 99 ns 6865572 BM_MatchedFullQuery 321 ns 320 ns 2206163 BM_UnmatchedSingleQuery 308 ns 308 ns 2270457 BM_UnmatchedFullQuery 313 ns 312 ns 2218307 BM_OneVariableFullMatch 449 ns 448 ns 1552719 BM_OneVariableMatchUnmatch 769 ns 768 ns 889476 New results: BM_MatchedSingleQuery 60 ns 60 ns 11614595 BM_MatchedFullQuery 314 ns 314 ns 2242016 BM_UnmatchedSingleQuery 56 ns 56 ns 12320256 BM_UnmatchedFullQuery 272 ns 272 ns 2609243 BM_OneVariableFullMatch 392 ns 392 ns 1783676 BM_OneVariableMatchUnmatch 476 ns 476 ns 1467029
1 parent 53bd030 commit c14e7d6

File tree

4 files changed

+205
-0
lines changed

4 files changed

+205
-0
lines changed

Framework/Core/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ set(TEST_SRCS
248248
test/test_WorkflowHelpers.cxx
249249
)
250250

251+
set(BENCH_SRCS test/benchmark_DataDescriptorMatcher.cxx)
252+
253+
O2_GENERATE_TESTS(
254+
MODULE_LIBRARY_NAME ${LIBRARY_NAME}
255+
BUCKET_NAME O2FrameworkCore_benchmark_bucket
256+
TEST_SRCS ${BENCH_SRCS}
257+
)
258+
251259
O2_GENERATE_TESTS(
252260
MODULE_LIBRARY_NAME ${LIBRARY_NAME}
253261
BUCKET_NAME ${BUCKET_NAME}

Framework/Core/include/Framework/DataDescriptorMatcher.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,16 @@ class DataDescriptorMatcher
277277
} else {
278278
throw std::runtime_error("Bad parsing tree");
279279
}
280+
// Common speedup.
281+
if (mOp == Op::And && leftValue == false) {
282+
return false;
283+
}
284+
if (mOp == Op::Or && leftValue == true) {
285+
return true;
286+
}
287+
if (mOp == Op::Just) {
288+
return leftValue;
289+
}
280290

281291
if (auto pval0 = std::get_if<OriginValueMatcher>(&mRight)) {
282292
rightValue = pval0->match(d, context);
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#include <benchmark/benchmark.h>
2+
#include "Headers/DataHeader.h"
3+
#include "Framework/DataDescriptorMatcher.h"
4+
5+
using namespace o2::header;
6+
using namespace o2::framework::data_matcher;
7+
8+
static void BM_MatchedSingleQuery(benchmark::State& state)
9+
{
10+
DataHeader header;
11+
header.dataOrigin = "TRD";
12+
header.dataDescription = "TRACKLET";
13+
header.subSpecification = 0;
14+
15+
DataDescriptorMatcher matcher{
16+
DataDescriptorMatcher::Op::Just,
17+
OriginValueMatcher{ "TRD" }
18+
};
19+
20+
std::vector<ContextElement> context;
21+
22+
for (auto _ : state) {
23+
matcher.match(header, context);
24+
}
25+
}
26+
27+
BENCHMARK(BM_MatchedSingleQuery);
28+
29+
static void BM_MatchedFullQuery(benchmark::State& state)
30+
{
31+
DataHeader header;
32+
header.dataOrigin = "TRD";
33+
header.dataDescription = "TRACKLET";
34+
header.subSpecification = 0;
35+
36+
DataDescriptorMatcher matcher{
37+
DataDescriptorMatcher::Op::And,
38+
OriginValueMatcher{ "TRD" },
39+
std::make_unique<DataDescriptorMatcher>(
40+
DataDescriptorMatcher::Op::And,
41+
DescriptionValueMatcher{ "TRACKLET" },
42+
std::make_unique<DataDescriptorMatcher>(
43+
DataDescriptorMatcher::Op::And,
44+
SubSpecificationTypeValueMatcher{ 0 },
45+
ConstantValueMatcher{ true }))
46+
};
47+
48+
std::vector<ContextElement> context;
49+
50+
for (auto _ : state) {
51+
matcher.match(header, context);
52+
}
53+
}
54+
// Register the function as a benchmark
55+
BENCHMARK(BM_MatchedFullQuery);
56+
57+
static void BM_UnmatchedSingleQuery(benchmark::State& state)
58+
{
59+
DataHeader header;
60+
header.dataOrigin = "TRD";
61+
header.dataDescription = "TRACKLET";
62+
header.subSpecification = 0;
63+
64+
DataDescriptorMatcher matcher{
65+
DataDescriptorMatcher::Op::And,
66+
OriginValueMatcher{ "TDR" },
67+
std::make_unique<DataDescriptorMatcher>(
68+
DataDescriptorMatcher::Op::And,
69+
DescriptionValueMatcher{ "TRACKLET" },
70+
std::make_unique<DataDescriptorMatcher>(
71+
DataDescriptorMatcher::Op::And,
72+
SubSpecificationTypeValueMatcher{ 1 },
73+
ConstantValueMatcher{ true }))
74+
};
75+
76+
std::vector<ContextElement> context;
77+
78+
for (auto _ : state) {
79+
matcher.match(header, context);
80+
}
81+
}
82+
83+
// Register the function as a benchmark
84+
BENCHMARK(BM_UnmatchedSingleQuery);
85+
86+
static void BM_UnmatchedFullQuery(benchmark::State& state)
87+
{
88+
DataHeader header;
89+
header.dataOrigin = "TRD";
90+
header.dataDescription = "TRACKLET";
91+
header.subSpecification = 0;
92+
93+
DataDescriptorMatcher matcher{
94+
DataDescriptorMatcher::Op::And,
95+
OriginValueMatcher{ "TRD" },
96+
std::make_unique<DataDescriptorMatcher>(
97+
DataDescriptorMatcher::Op::And,
98+
DescriptionValueMatcher{ "TRACKLET" },
99+
std::make_unique<DataDescriptorMatcher>(
100+
DataDescriptorMatcher::Op::And,
101+
SubSpecificationTypeValueMatcher{ 1 },
102+
ConstantValueMatcher{ true }))
103+
};
104+
105+
std::vector<ContextElement> context;
106+
107+
for (auto _ : state) {
108+
matcher.match(header, context);
109+
}
110+
}
111+
// Register the function as a benchmark
112+
BENCHMARK(BM_UnmatchedFullQuery);
113+
114+
static void BM_OneVariableFullMatch(benchmark::State& state)
115+
{
116+
DataHeader header;
117+
header.dataOrigin = "TRD";
118+
header.dataDescription = "TRACKLET";
119+
header.subSpecification = 0;
120+
121+
DataDescriptorMatcher matcher{
122+
DataDescriptorMatcher::Op::And,
123+
OriginValueMatcher{ ContextRef{ 0 } },
124+
std::make_unique<DataDescriptorMatcher>(
125+
DataDescriptorMatcher::Op::And,
126+
DescriptionValueMatcher{ "TRACKLET" },
127+
std::make_unique<DataDescriptorMatcher>(
128+
DataDescriptorMatcher::Op::And,
129+
SubSpecificationTypeValueMatcher{ 1 },
130+
ConstantValueMatcher{ true }))
131+
};
132+
133+
std::vector<ContextElement> context(1);
134+
135+
for (auto _ : state) {
136+
context[0].value = None{};
137+
matcher.match(header, context);
138+
}
139+
}
140+
// Register the function as a benchmark
141+
BENCHMARK(BM_OneVariableFullMatch);
142+
143+
static void BM_OneVariableMatchUnmatch(benchmark::State& state)
144+
{
145+
DataHeader header0;
146+
header0.dataOrigin = "TRD";
147+
header0.dataDescription = "TRACKLET";
148+
header0.subSpecification = 0;
149+
150+
DataHeader header1;
151+
header1.dataOrigin = "TPC";
152+
header1.dataDescription = "CLUSTERS";
153+
header1.subSpecification = 0;
154+
155+
DataDescriptorMatcher matcher{
156+
DataDescriptorMatcher::Op::And,
157+
OriginValueMatcher{ ContextRef{ 0 } },
158+
std::make_unique<DataDescriptorMatcher>(
159+
DataDescriptorMatcher::Op::And,
160+
DescriptionValueMatcher{ "TRACKLET" },
161+
std::make_unique<DataDescriptorMatcher>(
162+
DataDescriptorMatcher::Op::And,
163+
SubSpecificationTypeValueMatcher{ 1 },
164+
ConstantValueMatcher{ true }))
165+
};
166+
167+
std::vector<ContextElement> context(1);
168+
169+
for (auto _ : state) {
170+
context[0].value = None{};
171+
matcher.match(header0, context);
172+
matcher.match(header1, context);
173+
}
174+
}
175+
// Register the function as a benchmark
176+
BENCHMARK(BM_OneVariableMatchUnmatch);
177+
178+
BENCHMARK_MAIN();

cmake/O2Dependencies.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,15 @@ o2_define_bucket(
272272
${CMAKE_SOURCE_DIR}/Utilities/PCG/include
273273
)
274274

275+
o2_define_bucket(
276+
NAME
277+
O2FrameworkCore_benchmark_bucket
278+
279+
DEPENDENCIES
280+
O2FrameworkCore_bucket
281+
$<IF:$<BOOL:${benchmark_FOUND}>,benchmark::benchmark,$<0:"">>
282+
)
283+
275284
o2_define_bucket(
276285
NAME
277286
FrameworkApplication_bucket

0 commit comments

Comments
 (0)