1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20
21 #include <memory>
22
23 #include <benchmark/benchmark.h>
24
25 #include "perfetto/public/abi/atomic.h"
26 #include "perfetto/public/data_source.h"
27 #include "perfetto/public/pb_utils.h"
28 #include "perfetto/public/producer.h"
29 #include "perfetto/public/protos/trace/test_event.pzc.h"
30 #include "perfetto/public/protos/trace/trace.pzc.h"
31 #include "perfetto/public/protos/trace/trace_packet.pzc.h"
32 #include "perfetto/public/protos/trace/track_event/debug_annotation.pzc.h"
33 #include "perfetto/public/protos/trace/track_event/track_event.pzc.h"
34 #include "perfetto/public/te_category_macros.h"
35 #include "perfetto/public/te_macros.h"
36 #include "perfetto/public/track_event.h"
37
38 #include "src/shared_lib/test/utils.h"
39
40 static struct PerfettoDs custom = PERFETTO_DS_INIT();
41
42 #define BENCHMARK_CATEGORIES(C) C(benchmark_cat, "benchmark", "")
43
44 PERFETTO_TE_CATEGORIES_DEFINE(BENCHMARK_CATEGORIES)
45
46 namespace {
47
48 using ::perfetto::shlib::test_utils::FieldView;
49 using ::perfetto::shlib::test_utils::IdFieldView;
50 using ::perfetto::shlib::test_utils::TracingSession;
51
52 constexpr char kDataSourceName[] = "com.example.custom_data_source";
53
Initialize()54 bool Initialize() {
55 struct PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
56 args.backends = PERFETTO_BACKEND_IN_PROCESS;
57 PerfettoProducerInit(args);
58 PerfettoDsRegister(&custom, kDataSourceName, PerfettoDsParamsDefault());
59 PerfettoTeInit();
60 PERFETTO_TE_REGISTER_CATEGORIES(BENCHMARK_CATEGORIES);
61 return true;
62 }
63
EnsureInitialized()64 void EnsureInitialized() {
65 static bool initialized = Initialize();
66 (void)initialized;
67 }
68
DecodePacketSizes(const std::vector<uint8_t> & data)69 size_t DecodePacketSizes(const std::vector<uint8_t>& data) {
70 for (struct PerfettoPbDecoderField field :
71 IdFieldView(data, perfetto_protos_Trace_packet_field_number)) {
72 if (field.status != PERFETTO_PB_DECODER_OK ||
73 field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) {
74 abort();
75 }
76 IdFieldView for_testing_fields(
77 field, perfetto_protos_TracePacket_for_testing_field_number);
78 if (!for_testing_fields.ok()) {
79 abort();
80 }
81 if (for_testing_fields.size() == 0) {
82 continue;
83 }
84 if (for_testing_fields.size() > 1 || for_testing_fields.front().wire_type !=
85 PERFETTO_PB_WIRE_TYPE_DELIMITED) {
86 abort();
87 }
88 return field.value.delimited.len;
89 }
90
91 return 0;
92 }
93
BM_Shlib_DataSource_Disabled(benchmark::State & state)94 void BM_Shlib_DataSource_Disabled(benchmark::State& state) {
95 EnsureInitialized();
96 for (auto _ : state) {
97 PERFETTO_DS_TRACE(custom, ctx) {}
98 benchmark::ClobberMemory();
99 }
100 }
101
BM_Shlib_DataSource_DifferentPacketSize(benchmark::State & state)102 void BM_Shlib_DataSource_DifferentPacketSize(benchmark::State& state) {
103 EnsureInitialized();
104 TracingSession tracing_session =
105 TracingSession::Builder().set_data_source_name(kDataSourceName).Build();
106
107 // This controls the number of times a field is added in the trace packet.
108 // It controls the size of the trace packet. The PacketSize counter reports
109 // the exact number.
110 const size_t kNumFields = static_cast<size_t>(state.range(0));
111
112 for (auto _ : state) {
113 PERFETTO_DS_TRACE(custom, ctx) {
114 struct PerfettoDsRootTracePacket trace_packet;
115 PerfettoDsTracerPacketBegin(&ctx, &trace_packet);
116
117 {
118 struct perfetto_protos_TestEvent for_testing;
119 perfetto_protos_TracePacket_begin_for_testing(&trace_packet.msg,
120 &for_testing);
121 {
122 struct perfetto_protos_TestEvent_TestPayload payload;
123 perfetto_protos_TestEvent_begin_payload(&for_testing, &payload);
124 for (size_t i = 0; i < kNumFields; i++) {
125 perfetto_protos_TestEvent_TestPayload_set_cstr_str(&payload,
126 "ABCDEFGH");
127 }
128 perfetto_protos_TestEvent_end_payload(&for_testing, &payload);
129 }
130 perfetto_protos_TracePacket_end_for_testing(&trace_packet.msg,
131 &for_testing);
132 }
133 PerfettoDsTracerPacketEnd(&ctx, &trace_packet);
134 }
135 benchmark::ClobberMemory();
136 }
137
138 tracing_session.StopBlocking();
139 std::vector<uint8_t> data = tracing_session.ReadBlocking();
140
141 // Just compute the PacketSize counter.
142 state.counters["PacketSize"] = static_cast<double>(DecodePacketSizes(data));
143 }
144
BM_Shlib_TeDisabled(benchmark::State & state)145 void BM_Shlib_TeDisabled(benchmark::State& state) {
146 EnsureInitialized();
147 while (state.KeepRunning()) {
148 PERFETTO_TE(benchmark_cat, PERFETTO_TE_SLICE_BEGIN("DisabledEvent"));
149 benchmark::ClobberMemory();
150 }
151 }
152
BM_Shlib_TeBasic(benchmark::State & state)153 void BM_Shlib_TeBasic(benchmark::State& state) {
154 EnsureInitialized();
155 TracingSession tracing_session = TracingSession::Builder()
156 .set_data_source_name("track_event")
157 .add_enabled_category("*")
158 .Build();
159
160 while (state.KeepRunning()) {
161 PERFETTO_TE(benchmark_cat, PERFETTO_TE_SLICE_BEGIN("Event"));
162 benchmark::ClobberMemory();
163 }
164 }
165
BM_Shlib_TeBasicNoIntern(benchmark::State & state)166 void BM_Shlib_TeBasicNoIntern(benchmark::State& state) {
167 EnsureInitialized();
168 TracingSession tracing_session = TracingSession::Builder()
169 .set_data_source_name("track_event")
170 .add_enabled_category("*")
171 .Build();
172
173 while (state.KeepRunning()) {
174 PERFETTO_TE(benchmark_cat, PERFETTO_TE_SLICE_BEGIN("Event"),
175 PERFETTO_TE_NO_INTERN());
176 benchmark::ClobberMemory();
177 }
178 }
179
BM_Shlib_TeDebugAnnotations(benchmark::State & state)180 void BM_Shlib_TeDebugAnnotations(benchmark::State& state) {
181 EnsureInitialized();
182 TracingSession tracing_session = TracingSession::Builder()
183 .set_data_source_name("track_event")
184 .add_enabled_category("*")
185 .Build();
186
187 while (state.KeepRunning()) {
188 PERFETTO_TE(benchmark_cat, PERFETTO_TE_SLICE_BEGIN("Event"),
189 PERFETTO_TE_ARG_UINT64("value", 42));
190 benchmark::ClobberMemory();
191 }
192 }
193
BM_Shlib_TeCustomProto(benchmark::State & state)194 void BM_Shlib_TeCustomProto(benchmark::State& state) {
195 EnsureInitialized();
196 TracingSession tracing_session = TracingSession::Builder()
197 .set_data_source_name("track_event")
198 .add_enabled_category("*")
199 .Build();
200
201 while (state.KeepRunning()) {
202 PERFETTO_TE(
203 benchmark_cat, PERFETTO_TE_SLICE_BEGIN("Event"),
204 PERFETTO_TE_PROTO_FIELDS(PERFETTO_TE_PROTO_FIELD_NESTED(
205 perfetto_protos_TrackEvent_debug_annotations_field_number,
206 PERFETTO_TE_PROTO_FIELD_CSTR(
207 perfetto_protos_DebugAnnotation_name_field_number, "value"),
208 PERFETTO_TE_PROTO_FIELD_VARINT(
209 perfetto_protos_DebugAnnotation_uint_value_field_number, 42))));
210 benchmark::ClobberMemory();
211 }
212 }
213
BM_Shlib_TeLlBasic(benchmark::State & state)214 void BM_Shlib_TeLlBasic(benchmark::State& state) {
215 EnsureInitialized();
216 TracingSession tracing_session = TracingSession::Builder()
217 .set_data_source_name("track_event")
218 .add_enabled_category("*")
219 .Build();
220
221 while (state.KeepRunning()) {
222 if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
223 benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
224 struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
225 int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
226 const char* name = "Event";
227 for (struct PerfettoTeLlIterator ctx =
228 PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
229 ctx.impl.ds.tracer != nullptr;
230 PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
231 uint64_t name_iid;
232 {
233 struct PerfettoDsRootTracePacket trace_packet;
234 PerfettoTeLlPacketBegin(&ctx, &trace_packet);
235 PerfettoTeLlWriteTimestamp(&trace_packet.msg, ×tamp);
236 perfetto_protos_TracePacket_set_sequence_flags(
237 &trace_packet.msg,
238 perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
239 {
240 struct PerfettoTeLlInternContext intern_ctx;
241 PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
242 &trace_packet.msg);
243 PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
244 name_iid = PerfettoTeLlInternEventName(&intern_ctx, name);
245 PerfettoTeLlInternContextDestroy(&intern_ctx);
246 }
247 {
248 struct perfetto_protos_TrackEvent te_msg;
249 perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
250 &te_msg);
251 perfetto_protos_TrackEvent_set_type(
252 &te_msg,
253 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
254 PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
255 PerfettoTeLlWriteInternedEventName(&te_msg, name_iid);
256 perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
257 &te_msg);
258 }
259 PerfettoTeLlPacketEnd(&ctx, &trace_packet);
260 }
261 }
262 }
263
264 benchmark::ClobberMemory();
265 }
266 }
267
BM_Shlib_TeLlBasicNoIntern(benchmark::State & state)268 void BM_Shlib_TeLlBasicNoIntern(benchmark::State& state) {
269 EnsureInitialized();
270 TracingSession tracing_session = TracingSession::Builder()
271 .set_data_source_name("track_event")
272 .add_enabled_category("*")
273 .Build();
274
275 while (state.KeepRunning()) {
276 if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
277 benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
278 struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
279 int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
280 const char* name = "Event";
281 for (struct PerfettoTeLlIterator ctx =
282 PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
283 ctx.impl.ds.tracer != nullptr;
284 PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
285 {
286 struct PerfettoDsRootTracePacket trace_packet;
287 PerfettoTeLlPacketBegin(&ctx, &trace_packet);
288 PerfettoTeLlWriteTimestamp(&trace_packet.msg, ×tamp);
289 perfetto_protos_TracePacket_set_sequence_flags(
290 &trace_packet.msg,
291 perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
292 {
293 struct PerfettoTeLlInternContext intern_ctx;
294 PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
295 &trace_packet.msg);
296 PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
297 PerfettoTeLlInternContextDestroy(&intern_ctx);
298 }
299 {
300 struct perfetto_protos_TrackEvent te_msg;
301 perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
302 &te_msg);
303 perfetto_protos_TrackEvent_set_type(
304 &te_msg,
305 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
306 PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
307 PerfettoTeLlWriteEventName(&te_msg, name);
308 perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
309 &te_msg);
310 }
311 PerfettoTeLlPacketEnd(&ctx, &trace_packet);
312 }
313 }
314 }
315 benchmark::ClobberMemory();
316 }
317 }
318
BM_Shlib_TeLlDebugAnnotations(benchmark::State & state)319 void BM_Shlib_TeLlDebugAnnotations(benchmark::State& state) {
320 EnsureInitialized();
321 TracingSession tracing_session = TracingSession::Builder()
322 .set_data_source_name("track_event")
323 .add_enabled_category("*")
324 .Build();
325
326 while (state.KeepRunning()) {
327 if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
328 benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
329 struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
330 int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
331 const char* name = "Event";
332 for (struct PerfettoTeLlIterator ctx =
333 PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
334 ctx.impl.ds.tracer != nullptr;
335 PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
336 uint64_t name_iid;
337 uint64_t dbg_arg_iid;
338 {
339 struct PerfettoDsRootTracePacket trace_packet;
340 PerfettoTeLlPacketBegin(&ctx, &trace_packet);
341 PerfettoTeLlWriteTimestamp(&trace_packet.msg, ×tamp);
342 perfetto_protos_TracePacket_set_sequence_flags(
343 &trace_packet.msg,
344 perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
345 {
346 struct PerfettoTeLlInternContext intern_ctx;
347 PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
348 &trace_packet.msg);
349 PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
350 name_iid = PerfettoTeLlInternEventName(&intern_ctx, name);
351 dbg_arg_iid = PerfettoTeLlInternDbgArgName(&intern_ctx, "value");
352 PerfettoTeLlInternContextDestroy(&intern_ctx);
353 }
354 {
355 struct perfetto_protos_TrackEvent te_msg;
356 perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
357 &te_msg);
358 perfetto_protos_TrackEvent_set_type(
359 &te_msg,
360 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
361 PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
362 PerfettoTeLlWriteInternedEventName(&te_msg, name_iid);
363 {
364 struct perfetto_protos_DebugAnnotation dbg_arg;
365 perfetto_protos_TrackEvent_begin_debug_annotations(&te_msg,
366 &dbg_arg);
367 perfetto_protos_DebugAnnotation_set_name_iid(&dbg_arg,
368 dbg_arg_iid);
369 perfetto_protos_DebugAnnotation_set_uint_value(&dbg_arg, 42);
370 perfetto_protos_TrackEvent_end_debug_annotations(&te_msg,
371 &dbg_arg);
372 }
373 perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
374 &te_msg);
375 }
376 PerfettoTeLlPacketEnd(&ctx, &trace_packet);
377 }
378 }
379 }
380 benchmark::ClobberMemory();
381 }
382 }
383
BM_Shlib_TeLlCustomProto(benchmark::State & state)384 void BM_Shlib_TeLlCustomProto(benchmark::State& state) {
385 EnsureInitialized();
386 TracingSession tracing_session = TracingSession::Builder()
387 .set_data_source_name("track_event")
388 .add_enabled_category("*")
389 .Build();
390
391 while (state.KeepRunning()) {
392 if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
393 benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
394 struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
395 int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
396 const char* name = "Event";
397 for (struct PerfettoTeLlIterator ctx =
398 PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
399 ctx.impl.ds.tracer != nullptr;
400 PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
401 uint64_t name_iid;
402 {
403 struct PerfettoDsRootTracePacket trace_packet;
404 PerfettoTeLlPacketBegin(&ctx, &trace_packet);
405 PerfettoTeLlWriteTimestamp(&trace_packet.msg, ×tamp);
406 perfetto_protos_TracePacket_set_sequence_flags(
407 &trace_packet.msg,
408 perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
409 {
410 struct PerfettoTeLlInternContext intern_ctx;
411 PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
412 &trace_packet.msg);
413 PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
414 name_iid = PerfettoTeLlInternEventName(&intern_ctx, name);
415 PerfettoTeLlInternContextDestroy(&intern_ctx);
416 }
417 {
418 struct perfetto_protos_TrackEvent te_msg;
419 perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
420 &te_msg);
421 perfetto_protos_TrackEvent_set_type(
422 &te_msg,
423 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
424 PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
425 PerfettoTeLlWriteInternedEventName(&te_msg, name_iid);
426 {
427 struct perfetto_protos_DebugAnnotation dbg_arg;
428 perfetto_protos_TrackEvent_begin_debug_annotations(&te_msg,
429 &dbg_arg);
430 perfetto_protos_DebugAnnotation_set_cstr_name(&dbg_arg, "value");
431 perfetto_protos_DebugAnnotation_set_uint_value(&dbg_arg, 42);
432 perfetto_protos_TrackEvent_end_debug_annotations(&te_msg,
433 &dbg_arg);
434 }
435 perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
436 &te_msg);
437 }
438 PerfettoTeLlPacketEnd(&ctx, &trace_packet);
439 }
440 }
441 }
442 benchmark::ClobberMemory();
443 }
444 }
445
446 } // namespace
447
448 BENCHMARK(BM_Shlib_DataSource_Disabled);
449 BENCHMARK(BM_Shlib_DataSource_DifferentPacketSize)->Range(1, 1000);
450 BENCHMARK(BM_Shlib_TeDisabled);
451 BENCHMARK(BM_Shlib_TeBasic);
452 BENCHMARK(BM_Shlib_TeBasicNoIntern);
453 BENCHMARK(BM_Shlib_TeDebugAnnotations);
454 BENCHMARK(BM_Shlib_TeCustomProto);
455 BENCHMARK(BM_Shlib_TeLlBasic);
456 BENCHMARK(BM_Shlib_TeLlBasicNoIntern);
457 BENCHMARK(BM_Shlib_TeLlDebugAnnotations);
458 BENCHMARK(BM_Shlib_TeLlCustomProto);
459