• 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/data_source.h"
26 #include "perfetto/public/pb_utils.h"
27 #include "perfetto/public/producer.h"
28 #include "perfetto/public/protos/trace/test_event.pzc.h"
29 #include "perfetto/public/protos/trace/trace.pzc.h"
30 #include "perfetto/public/protos/trace/trace_packet.pzc.h"
31 
32 #include "src/shared_lib/test/utils.h"
33 
34 static struct PerfettoDs custom = PERFETTO_DS_INIT();
35 
36 namespace {
37 
38 using ::perfetto::shlib::test_utils::FieldView;
39 using ::perfetto::shlib::test_utils::IdFieldView;
40 using ::perfetto::shlib::test_utils::TracingSession;
41 
42 constexpr char kDataSourceName[] = "com.example.custom_data_source";
43 
Initialize()44 bool Initialize() {
45   struct PerfettoProducerInitArgs args = {0};
46   args.backends = PERFETTO_BACKEND_IN_PROCESS;
47   PerfettoProducerInit(args);
48   PerfettoDsRegister(&custom, kDataSourceName, PerfettoDsNoCallbacks());
49   return true;
50 }
51 
EnsureInitialized()52 void EnsureInitialized() {
53   static bool initialized = Initialize();
54   (void)initialized;
55 }
56 
DecodePacketSizes(const std::vector<uint8_t> & data)57 size_t DecodePacketSizes(const std::vector<uint8_t>& data) {
58   for (struct PerfettoPbDecoderField field :
59        IdFieldView(data, perfetto_protos_Trace_packet_field_number)) {
60     if (field.status != PERFETTO_PB_DECODER_OK ||
61         field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) {
62       abort();
63     }
64     IdFieldView for_testing_fields(
65         field, perfetto_protos_TracePacket_for_testing_field_number);
66     if (!for_testing_fields.ok()) {
67       abort();
68     }
69     if (for_testing_fields.size() == 0) {
70       continue;
71     }
72     if (for_testing_fields.size() > 1 || for_testing_fields.front().wire_type !=
73                                              PERFETTO_PB_WIRE_TYPE_DELIMITED) {
74       abort();
75     }
76     return field.value.delimited.len;
77   }
78 
79   return 0;
80 }
81 
BM_Shlib_DataSource_Disabled(benchmark::State & state)82 void BM_Shlib_DataSource_Disabled(benchmark::State& state) {
83   EnsureInitialized();
84   for (auto _ : state) {
85     PERFETTO_DS_TRACE(custom, ctx) {}
86     benchmark::ClobberMemory();
87   }
88 }
89 
BM_Shlib_DataSource_DifferentPacketSize(benchmark::State & state)90 void BM_Shlib_DataSource_DifferentPacketSize(benchmark::State& state) {
91   EnsureInitialized();
92   TracingSession tracing_session =
93       TracingSession::Builder().set_data_source_name(kDataSourceName).Build();
94 
95   // This controls the number of times a field is added in the trace packet.
96   // It controls the size of the trace packet. The PacketSize counter reports
97   // the exact number.
98   const size_t kNumFields = static_cast<size_t>(state.range(0));
99 
100   for (auto _ : state) {
101     PERFETTO_DS_TRACE(custom, ctx) {
102       struct PerfettoDsRootTracePacket trace_packet;
103       PerfettoDsTracerPacketBegin(&ctx, &trace_packet);
104 
105       {
106         struct perfetto_protos_TestEvent for_testing;
107         perfetto_protos_TracePacket_begin_for_testing(&trace_packet.msg,
108                                                       &for_testing);
109         {
110           struct perfetto_protos_TestEvent_TestPayload payload;
111           perfetto_protos_TestEvent_begin_payload(&for_testing, &payload);
112           for (size_t i = 0; i < kNumFields; i++) {
113             perfetto_protos_TestEvent_TestPayload_set_cstr_str(&payload,
114                                                                "ABCDEFGH");
115           }
116           perfetto_protos_TestEvent_end_payload(&for_testing, &payload);
117         }
118         perfetto_protos_TracePacket_end_for_testing(&trace_packet.msg,
119                                                     &for_testing);
120       }
121       PerfettoDsTracerPacketEnd(&ctx, &trace_packet);
122     }
123     benchmark::ClobberMemory();
124   }
125 
126   tracing_session.StopBlocking();
127   std::vector<uint8_t> data = tracing_session.ReadBlocking();
128 
129   // Just compute the PacketSize counter.
130   state.counters["PacketSize"] = static_cast<double>(DecodePacketSizes(data));
131 }
132 
133 }  // namespace
134 
135 BENCHMARK(BM_Shlib_DataSource_Disabled);
136 BENCHMARK(BM_Shlib_DataSource_DifferentPacketSize)->Range(1, 1000);
137