• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TeLlBasic(benchmark::State & state)194 void BM_Shlib_TeLlBasic(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     if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
203             benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
204       struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
205       int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
206       const char* name = "Event";
207       for (struct PerfettoTeLlIterator ctx =
208                PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
209            ctx.impl.ds.tracer != nullptr;
210            PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
211         uint64_t name_iid;
212         {
213           struct PerfettoDsRootTracePacket trace_packet;
214           PerfettoTeLlPacketBegin(&ctx, &trace_packet);
215           PerfettoTeLlWriteTimestamp(&trace_packet.msg, &timestamp);
216           perfetto_protos_TracePacket_set_sequence_flags(
217               &trace_packet.msg,
218               perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
219           {
220             struct PerfettoTeLlInternContext intern_ctx;
221             PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
222                                           &trace_packet.msg);
223             PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
224             name_iid = PerfettoTeLlInternEventName(&intern_ctx, name);
225             PerfettoTeLlInternContextDestroy(&intern_ctx);
226           }
227           {
228             struct perfetto_protos_TrackEvent te_msg;
229             perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
230                                                           &te_msg);
231             perfetto_protos_TrackEvent_set_type(
232                 &te_msg,
233                 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
234             PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
235             PerfettoTeLlWriteInternedEventName(&te_msg, name_iid);
236             perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
237                                                         &te_msg);
238           }
239           PerfettoTeLlPacketEnd(&ctx, &trace_packet);
240         }
241       }
242     }
243 
244     benchmark::ClobberMemory();
245   }
246 }
247 
BM_Shlib_TeLlBasicNoIntern(benchmark::State & state)248 void BM_Shlib_TeLlBasicNoIntern(benchmark::State& state) {
249   EnsureInitialized();
250   TracingSession tracing_session = TracingSession::Builder()
251                                        .set_data_source_name("track_event")
252                                        .add_enabled_category("*")
253                                        .Build();
254 
255   while (state.KeepRunning()) {
256     if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
257             benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
258       struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
259       int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
260       const char* name = "Event";
261       for (struct PerfettoTeLlIterator ctx =
262                PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
263            ctx.impl.ds.tracer != nullptr;
264            PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
265         {
266           struct PerfettoDsRootTracePacket trace_packet;
267           PerfettoTeLlPacketBegin(&ctx, &trace_packet);
268           PerfettoTeLlWriteTimestamp(&trace_packet.msg, &timestamp);
269           perfetto_protos_TracePacket_set_sequence_flags(
270               &trace_packet.msg,
271               perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
272           {
273             struct PerfettoTeLlInternContext intern_ctx;
274             PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
275                                           &trace_packet.msg);
276             PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
277             PerfettoTeLlInternContextDestroy(&intern_ctx);
278           }
279           {
280             struct perfetto_protos_TrackEvent te_msg;
281             perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
282                                                           &te_msg);
283             perfetto_protos_TrackEvent_set_type(
284                 &te_msg,
285                 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
286             PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
287             PerfettoTeLlWriteEventName(&te_msg, name);
288             perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
289                                                         &te_msg);
290           }
291           PerfettoTeLlPacketEnd(&ctx, &trace_packet);
292         }
293       }
294     }
295     benchmark::ClobberMemory();
296   }
297 }
298 
BM_Shlib_TeLlDebugAnnotations(benchmark::State & state)299 void BM_Shlib_TeLlDebugAnnotations(benchmark::State& state) {
300   EnsureInitialized();
301   TracingSession tracing_session = TracingSession::Builder()
302                                        .set_data_source_name("track_event")
303                                        .add_enabled_category("*")
304                                        .Build();
305 
306   while (state.KeepRunning()) {
307     if (PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
308             benchmark_cat.enabled, PERFETTO_MEMORY_ORDER_RELAXED))) {
309       struct PerfettoTeTimestamp timestamp = PerfettoTeGetTimestamp();
310       int32_t type = PERFETTO_TE_TYPE_SLICE_BEGIN;
311       const char* name = "Event";
312       for (struct PerfettoTeLlIterator ctx =
313                PerfettoTeLlBeginSlowPath(&benchmark_cat, timestamp);
314            ctx.impl.ds.tracer != nullptr;
315            PerfettoTeLlNext(&benchmark_cat, timestamp, &ctx)) {
316         uint64_t name_iid;
317         uint64_t dbg_arg_iid;
318         {
319           struct PerfettoDsRootTracePacket trace_packet;
320           PerfettoTeLlPacketBegin(&ctx, &trace_packet);
321           PerfettoTeLlWriteTimestamp(&trace_packet.msg, &timestamp);
322           perfetto_protos_TracePacket_set_sequence_flags(
323               &trace_packet.msg,
324               perfetto_protos_TracePacket_SEQ_NEEDS_INCREMENTAL_STATE);
325           {
326             struct PerfettoTeLlInternContext intern_ctx;
327             PerfettoTeLlInternContextInit(&intern_ctx, ctx.impl.incr,
328                                           &trace_packet.msg);
329             PerfettoTeLlInternRegisteredCat(&intern_ctx, &benchmark_cat);
330             name_iid = PerfettoTeLlInternEventName(&intern_ctx, name);
331             dbg_arg_iid = PerfettoTeLlInternDbgArgName(&intern_ctx, "value");
332             PerfettoTeLlInternContextDestroy(&intern_ctx);
333           }
334           {
335             struct perfetto_protos_TrackEvent te_msg;
336             perfetto_protos_TracePacket_begin_track_event(&trace_packet.msg,
337                                                           &te_msg);
338             perfetto_protos_TrackEvent_set_type(
339                 &te_msg,
340                 static_cast<enum perfetto_protos_TrackEvent_Type>(type));
341             PerfettoTeLlWriteRegisteredCat(&te_msg, &benchmark_cat);
342             PerfettoTeLlWriteInternedEventName(&te_msg, name_iid);
343             {
344               struct perfetto_protos_DebugAnnotation dbg_arg;
345               perfetto_protos_TrackEvent_begin_debug_annotations(&te_msg,
346                                                                  &dbg_arg);
347               perfetto_protos_DebugAnnotation_set_name_iid(&dbg_arg,
348                                                            dbg_arg_iid);
349               perfetto_protos_DebugAnnotation_set_uint_value(&dbg_arg, 42);
350               perfetto_protos_TrackEvent_end_debug_annotations(&te_msg,
351                                                                &dbg_arg);
352             }
353             perfetto_protos_TracePacket_end_track_event(&trace_packet.msg,
354                                                         &te_msg);
355           }
356           PerfettoTeLlPacketEnd(&ctx, &trace_packet);
357         }
358       }
359     }
360     benchmark::ClobberMemory();
361   }
362 }
363 
364 }  // namespace
365 
366 BENCHMARK(BM_Shlib_DataSource_Disabled);
367 BENCHMARK(BM_Shlib_DataSource_DifferentPacketSize)->Range(1, 1000);
368 BENCHMARK(BM_Shlib_TeDisabled);
369 BENCHMARK(BM_Shlib_TeBasic);
370 BENCHMARK(BM_Shlib_TeBasicNoIntern);
371 BENCHMARK(BM_Shlib_TeDebugAnnotations);
372 BENCHMARK(BM_Shlib_TeLlBasic);
373 BENCHMARK(BM_Shlib_TeLlBasicNoIntern);
374 BENCHMARK(BM_Shlib_TeLlDebugAnnotations);
375