• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <benchmark/benchmark.h>
3 #include <string.h>
4 
5 #include "absl/container/flat_hash_set.h"
6 #include "benchmarks/descriptor.pb.h"
7 #include "benchmarks/descriptor.upb.h"
8 #include "benchmarks/descriptor.upbdefs.h"
9 #include "benchmarks/descriptor_sv.pb.h"
10 #include "google/ads/googleads/v5/services/google_ads_service.upbdefs.h"
11 #include "google/protobuf/descriptor.pb.h"
12 #include "upb/def.hpp"
13 
14 upb_strview descriptor = benchmarks_descriptor_proto_upbdefinit.descriptor;
15 namespace protobuf = ::google::protobuf;
16 
17 /* A buffer big enough to parse descriptor.proto without going to heap. */
18 char buf[65535];
19 
CollectFileDescriptors(const upb_def_init * file,std::vector<upb_strview> & serialized_files,absl::flat_hash_set<const upb_def_init * > & seen)20 void CollectFileDescriptors(const upb_def_init* file,
21                             std::vector<upb_strview>& serialized_files,
22                             absl::flat_hash_set<const upb_def_init*>& seen) {
23   if (!seen.insert(file).second) return;
24   for (upb_def_init **deps = file->deps; *deps; deps++) {
25     CollectFileDescriptors(*deps, serialized_files, seen);
26   }
27   serialized_files.push_back(file->descriptor);
28 }
29 
BM_ArenaOneAlloc(benchmark::State & state)30 static void BM_ArenaOneAlloc(benchmark::State& state) {
31   for (auto _ : state) {
32     upb_arena* arena = upb_arena_new();
33     upb_arena_malloc(arena, 1);
34     upb_arena_free(arena);
35   }
36 }
37 BENCHMARK(BM_ArenaOneAlloc);
38 
BM_ArenaInitialBlockOneAlloc(benchmark::State & state)39 static void BM_ArenaInitialBlockOneAlloc(benchmark::State& state) {
40   for (auto _ : state) {
41     upb_arena* arena = upb_arena_init(buf, sizeof(buf), NULL);
42     upb_arena_malloc(arena, 1);
43     upb_arena_free(arena);
44   }
45 }
46 BENCHMARK(BM_ArenaInitialBlockOneAlloc);
47 
BM_LoadDescriptor_Upb(benchmark::State & state)48 static void BM_LoadDescriptor_Upb(benchmark::State& state) {
49   size_t bytes_per_iter = 0;
50   for (auto _ : state) {
51     upb::SymbolTable symtab;
52     upb_benchmark_DescriptorProto_getmsgdef(symtab.ptr());
53     bytes_per_iter = _upb_symtab_bytesloaded(symtab.ptr());
54   }
55   state.SetBytesProcessed(state.iterations() * bytes_per_iter);
56 }
57 BENCHMARK(BM_LoadDescriptor_Upb);
58 
BM_LoadAdsDescriptor_Upb(benchmark::State & state)59 static void BM_LoadAdsDescriptor_Upb(benchmark::State& state) {
60   size_t bytes_per_iter = 0;
61   for (auto _ : state) {
62     upb::SymbolTable symtab;
63     google_ads_googleads_v5_services_SearchGoogleAdsRequest_getmsgdef(
64         symtab.ptr());
65     bytes_per_iter = _upb_symtab_bytesloaded(symtab.ptr());
66   }
67   state.SetBytesProcessed(state.iterations() * bytes_per_iter);
68 }
69 BENCHMARK(BM_LoadAdsDescriptor_Upb);
70 
BM_LoadDescriptor_Proto2(benchmark::State & state)71 static void BM_LoadDescriptor_Proto2(benchmark::State& state) {
72   for (auto _ : state) {
73     protobuf::Arena arena;
74     protobuf::StringPiece input(descriptor.data,descriptor.size);
75     auto proto = protobuf::Arena::CreateMessage<protobuf::FileDescriptorProto>(
76         &arena);
77     protobuf::DescriptorPool pool;
78     bool ok = proto->ParseFrom<protobuf::MessageLite::kMergePartial>(input) &&
79               pool.BuildFile(*proto) != nullptr;
80     if (!ok) {
81       printf("Failed to add file.\n");
82       exit(1);
83     }
84   }
85   state.SetBytesProcessed(state.iterations() * descriptor.size);
86 }
87 BENCHMARK(BM_LoadDescriptor_Proto2);
88 
BM_LoadAdsDescriptor_Proto2(benchmark::State & state)89 static void BM_LoadAdsDescriptor_Proto2(benchmark::State& state) {
90   extern upb_def_init google_ads_googleads_v5_services_google_ads_service_proto_upbdefinit;
91   std::vector<upb_strview> serialized_files;
92   absl::flat_hash_set<const upb_def_init*> seen_files;
93   CollectFileDescriptors(
94       &google_ads_googleads_v5_services_google_ads_service_proto_upbdefinit,
95       serialized_files, seen_files);
96   size_t bytes_per_iter = 0;
97   for (auto _ : state) {
98     bytes_per_iter = 0;
99     protobuf::Arena arena;
100     protobuf::DescriptorPool pool;
101     for (auto file : serialized_files) {
102       protobuf::StringPiece input(file.data, file.size);
103       auto proto = protobuf::Arena::CreateMessage<protobuf::FileDescriptorProto>(
104           &arena);
105       bool ok = proto->ParseFrom<protobuf::MessageLite::kMergePartial>(input) &&
106                 pool.BuildFile(*proto) != nullptr;
107       if (!ok) {
108         printf("Failed to add file.\n");
109         exit(1);
110       }
111       bytes_per_iter += input.size();
112     }
113   }
114   state.SetBytesProcessed(state.iterations() * bytes_per_iter);
115 }
116 BENCHMARK(BM_LoadAdsDescriptor_Proto2);
117 
118 enum CopyStrings {
119   Copy,
120   Alias,
121 };
122 
123 enum ArenaMode {
124   NoArena,
125   UseArena,
126   InitBlock,
127 };
128 
129 template <ArenaMode AMode, CopyStrings Copy>
BM_Parse_Upb_FileDesc(benchmark::State & state)130 static void BM_Parse_Upb_FileDesc(benchmark::State& state) {
131   size_t bytes = 0;
132   for (auto _ : state) {
133     upb_arena *arena;
134     if (AMode == InitBlock) {
135       arena = upb_arena_init(buf, sizeof(buf), NULL);
136     } else {
137       arena = upb_arena_new();
138     }
139     upb_benchmark_FileDescriptorProto* set =
140         upb_benchmark_FileDescriptorProto_parse_ex(
141             descriptor.data, descriptor.size, arena,
142             Copy == Alias ? UPB_DECODE_ALIAS : 0);
143     if (!set) {
144       printf("Failed to parse.\n");
145       exit(1);
146     }
147     bytes += descriptor.size;
148     upb_arena_free(arena);
149   }
150   state.SetBytesProcessed(state.iterations() * descriptor.size);
151 }
152 BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, UseArena, Copy);
153 BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, UseArena, Alias);
154 BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, InitBlock, Copy);
155 BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, InitBlock, Alias);
156 
157 template <ArenaMode AMode, class P>
158 struct Proto2Factory;
159 
160 template<class P>
161 struct Proto2Factory<NoArena, P> {
162  public:
GetProtoProto2Factory163   P* GetProto() { return &proto_; }
164 
165  private:
166   P proto_;
167 };
168 
169 template <class P>
170 struct Proto2Factory<UseArena, P> {
171  public:
GetProtoProto2Factory172   P* GetProto() { return protobuf::Arena::CreateMessage<P>(&arena_); }
173 
174  private:
175   protobuf::Arena arena_;
176 };
177 
178 template <class P>
179 struct Proto2Factory<InitBlock, P> {
180  public:
Proto2FactoryProto2Factory181   Proto2Factory() : arena_(GetOptions()) {}
GetProtoProto2Factory182   P* GetProto() { return protobuf::Arena::CreateMessage<P>(&arena_); }
183 
184  private:
GetOptionsProto2Factory185   protobuf::ArenaOptions GetOptions() {
186     protobuf::ArenaOptions opts;
187     opts.initial_block = buf;
188     opts.initial_block_size = sizeof(buf);
189     return opts;
190   }
191 
192   protobuf::Arena arena_;
193 };
194 
195 using FileDesc = ::upb_benchmark::FileDescriptorProto;
196 using FileDescSV = ::upb_benchmark::sv::FileDescriptorProto;
197 
198 template <class P, ArenaMode AMode, CopyStrings kCopy>
BM_Parse_Proto2(benchmark::State & state)199 void BM_Parse_Proto2(benchmark::State& state) {
200   size_t bytes = 0;
201   constexpr protobuf::MessageLite::ParseFlags kParseFlags =
202       kCopy == Copy
203           ? protobuf::MessageLite::ParseFlags::kMergePartial
204           : protobuf::MessageLite::ParseFlags::kMergePartialWithAliasing;
205   for (auto _ : state) {
206     Proto2Factory<AMode, P> proto_factory;
207     auto proto = proto_factory.GetProto();
208     protobuf::StringPiece input(descriptor.data,descriptor.size);
209     bool ok = proto->template ParseFrom<kParseFlags>(input);
210     if (!ok) {
211       printf("Failed to parse.\n");
212       exit(1);
213     }
214     bytes += descriptor.size;
215   }
216   state.SetBytesProcessed(state.iterations() * descriptor.size);
217 }
218 BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, NoArena, Copy);
219 BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, UseArena, Copy);
220 BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, InitBlock, Copy);
221 BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, InitBlock, Alias);
222 
BM_SerializeDescriptor_Proto2(benchmark::State & state)223 static void BM_SerializeDescriptor_Proto2(benchmark::State& state) {
224   size_t bytes = 0;
225   upb_benchmark::FileDescriptorProto proto;
226   proto.ParseFromArray(descriptor.data, descriptor.size);
227   for (auto _ : state) {
228     proto.SerializePartialToArray(buf, sizeof(buf));
229     bytes += descriptor.size;
230   }
231   state.SetBytesProcessed(state.iterations() * descriptor.size);
232 }
233 BENCHMARK(BM_SerializeDescriptor_Proto2);
234 
BM_SerializeDescriptor_Upb(benchmark::State & state)235 static void BM_SerializeDescriptor_Upb(benchmark::State& state) {
236   int64_t total = 0;
237   upb_arena* arena = upb_arena_new();
238   upb_benchmark_FileDescriptorProto* set =
239       upb_benchmark_FileDescriptorProto_parse(descriptor.data, descriptor.size,
240                                               arena);
241   if (!set) {
242     printf("Failed to parse.\n");
243     exit(1);
244   }
245   for (auto _ : state) {
246     upb_arena* enc_arena = upb_arena_init(buf, sizeof(buf), NULL);
247     size_t size;
248     char* data =
249         upb_benchmark_FileDescriptorProto_serialize(set, enc_arena, &size);
250     if (!data) {
251       printf("Failed to serialize.\n");
252       exit(1);
253     }
254     total += size;
255   }
256   state.SetBytesProcessed(total);
257 }
258 BENCHMARK(BM_SerializeDescriptor_Upb);
259