xref: /aosp_15_r20/external/perfetto/src/shared_lib/test/benchmark.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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, &timestamp);
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, &timestamp);
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, &timestamp);
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, &timestamp);
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