diff --git a/benchmarks/benchmark.cc b/benchmarks/benchmark.cc index cc510bdd6c..7f4765a88c 100644 --- a/benchmarks/benchmark.cc +++ b/benchmarks/benchmark.cc @@ -115,31 +115,31 @@ static void BM_LoadAdsDescriptor_Proto2(benchmark::State& state) { } BENCHMARK(BM_LoadAdsDescriptor_Proto2); -static void BM_Parse_Upb_FileDesc_WithArena(benchmark::State& state) { - size_t bytes = 0; - for (auto _ : state) { - upb_arena* arena = upb_arena_new(); - upb_benchmark_FileDescriptorProto* set = - upb_benchmark_FileDescriptorProto_parse(descriptor.data, - descriptor.size, arena); - if (!set) { - printf("Failed to parse.\n"); - exit(1); - } - bytes += descriptor.size; - upb_arena_free(arena); - } - state.SetBytesProcessed(state.iterations() * descriptor.size); -} -BENCHMARK(BM_Parse_Upb_FileDesc_WithArena); +enum CopyStrings { + Copy, + Alias, +}; + +enum ArenaMode { + NoArena, + UseArena, + InitBlock, +}; -static void BM_Parse_Upb_FileDesc_WithInitialBlock(benchmark::State& state) { +template +static void BM_Parse_Upb_FileDesc(benchmark::State& state) { size_t bytes = 0; for (auto _ : state) { - upb_arena* arena = upb_arena_init(buf, sizeof(buf), NULL); + upb_arena *arena; + if (AMode == InitBlock) { + arena = upb_arena_init(buf, sizeof(buf), NULL); + } else { + arena = upb_arena_new(); + } upb_benchmark_FileDescriptorProto* set = - upb_benchmark_FileDescriptorProto_parse(descriptor.data, - descriptor.size, arena); + upb_benchmark_FileDescriptorProto_parse_ex( + descriptor.data, descriptor.size, arena, + Copy == Alias ? UPB_DECODE_ALIAS : 0); if (!set) { printf("Failed to parse.\n"); exit(1); @@ -149,10 +149,16 @@ static void BM_Parse_Upb_FileDesc_WithInitialBlock(benchmark::State& state) { } state.SetBytesProcessed(state.iterations() * descriptor.size); } -BENCHMARK(BM_Parse_Upb_FileDesc_WithInitialBlock); +BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, UseArena, Copy); +BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, UseArena, Alias); +BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, InitBlock, Copy); +BENCHMARK_TEMPLATE(BM_Parse_Upb_FileDesc, InitBlock, Alias); -template -struct NoArena { +template +struct Proto2Factory; + +template +struct Proto2Factory { public: P* GetProto() { return &proto_; } @@ -161,7 +167,7 @@ struct NoArena { }; template -struct WithArena { +struct Proto2Factory { public: P* GetProto() { return protobuf::Arena::CreateMessage

(&arena_); } @@ -170,9 +176,9 @@ struct WithArena { }; template -struct WithInitialBlock { +struct Proto2Factory { public: - WithInitialBlock() : arena_(GetOptions()) {} + Proto2Factory() : arena_(GetOptions()) {} P* GetProto() { return protobuf::Arena::CreateMessage

(&arena_); } private: @@ -189,17 +195,15 @@ struct WithInitialBlock { using FileDesc = ::upb_benchmark::FileDescriptorProto; using FileDescSV = ::upb_benchmark::sv::FileDescriptorProto; -const protobuf::MessageLite::ParseFlags kMergePartial = - protobuf::MessageLite::ParseFlags::kMergePartial; -const protobuf::MessageLite::ParseFlags kAlias = - protobuf::MessageLite::ParseFlags::kMergePartialWithAliasing; - -template class Factory, - protobuf::MessageLite::ParseFlags kParseFlags = kMergePartial> +template void BM_Parse_Proto2(benchmark::State& state) { size_t bytes = 0; + constexpr protobuf::MessageLite::ParseFlags kParseFlags = + kCopy == Copy + ? protobuf::MessageLite::ParseFlags::kMergePartial + : protobuf::MessageLite::ParseFlags::kMergePartialWithAliasing; for (auto _ : state) { - Factory

proto_factory; + Proto2Factory proto_factory; auto proto = proto_factory.GetProto(); protobuf::StringPiece input(descriptor.data,descriptor.size); bool ok = proto->template ParseFrom(input); @@ -211,15 +215,10 @@ void BM_Parse_Proto2(benchmark::State& state) { } state.SetBytesProcessed(state.iterations() * descriptor.size); } -BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, NoArena); -BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, WithArena); -BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, WithInitialBlock); -//BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, NoArena); -//BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, WithArena); -BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, WithInitialBlock); -//BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, NoArena, kAlias); -//BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, WithArena, kAlias); -BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, WithInitialBlock, kAlias); +BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, NoArena, Copy); +BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, UseArena, Copy); +BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDesc, InitBlock, Copy); +BENCHMARK_TEMPLATE(BM_Parse_Proto2, FileDescSV, InitBlock, Alias); static void BM_SerializeDescriptor_Proto2(benchmark::State& state) { size_t bytes = 0; diff --git a/upb/decode.c b/upb/decode.c index d38b46d7b8..f49918ecaf 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -643,10 +643,11 @@ const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, return decode_msg(d, ptr, msg, decode_totablep(table)); } -bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, - upb_arena *arena) { +bool _upb_decode(const char *buf, size_t size, void *msg, + const upb_msglayout *l, upb_arena *arena, int options) { bool ok; upb_decstate state; + unsigned depth = (unsigned)options >> 16; if (size == 0) { return true; @@ -660,12 +661,12 @@ bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, } else { state.end = buf + size - 16; state.limit = 16; - state.alias = true; + state.alias = options & UPB_DECODE_ALIAS; } state.limit_ptr = state.end; state.unknown_msg = NULL; - state.depth = 64; + state.depth = depth ? depth : 64; state.end_group = DECODE_NOGROUP; state.arena.head = arena->head; state.arena.last_size = arena->last_size; diff --git a/upb/decode.h b/upb/decode.h index 9de8638de5..00419ab373 100644 --- a/upb/decode.h +++ b/upb/decode.h @@ -7,15 +7,32 @@ #include "upb/msg.h" +/* Must be last. */ +#include "upb/port_def.inc" + #ifdef __cplusplus extern "C" { #endif +enum { + UPB_DECODE_ALIAS = 1, +}; + +#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16) + +bool _upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena, int options); + +UPB_INLINE bool upb_decode(const char *buf, size_t size, upb_msg *msg, - const upb_msglayout *l, upb_arena *arena); + const upb_msglayout *l, upb_arena *arena) { + return _upb_decode(buf, size, msg, l, arena, 0); +} #ifdef __cplusplus } /* extern "C" */ #endif +#include "upb/port_undef.inc" + #endif /* UPB_DECODE_H_ */ diff --git a/upb/decode_fast.c b/upb/decode_fast.c index f58f70ebec..f628e6dbd4 100644 --- a/upb/decode_fast.c +++ b/upb/decode_fast.c @@ -763,7 +763,7 @@ again: } else if (UPB_LIKELY(size <= 64)) { if (UPB_UNLIKELY(common_has < 64)) goto longstr; fastdecode_docopy(d, ptr, size, 64, buf, dst); - } else if (UPB_LIKELY(size <= 128)) { + } else if (UPB_LIKELY(size < 128)) { if (UPB_UNLIKELY(common_has < 128)) goto longstr; fastdecode_docopy(d, ptr, size, 128, buf, dst); } else { diff --git a/upb/def.c b/upb/def.c index 19b30fe7ae..74c33ccb17 100644 --- a/upb/def.c +++ b/upb/def.c @@ -2140,8 +2140,8 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { if (!_upb_symtab_loaddefinit(s, *deps)) goto err; } - file = google_protobuf_FileDescriptorProto_parse( - init->descriptor.data, init->descriptor.size, arena); + file = google_protobuf_FileDescriptorProto_parse_ex( + init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS); s->bytes_loaded += init->descriptor.size; if (!file) { diff --git a/upbc/generator.cc b/upbc/generator.cc index f4d1bb9b8d..4f9db9ad91 100644 --- a/upbc/generator.cc +++ b/upbc/generator.cc @@ -348,6 +348,12 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output " $0 *ret = $0_new(arena);\n" " return (ret && upb_decode(buf, size, ret, &$1, arena)) ? ret : NULL;\n" "}\n" + "UPB_INLINE $0 *$0_parse_ex(const char *buf, size_t size,\n" + " upb_arena *arena, int options) {\n" + " $0 *ret = $0_new(arena);\n" + " return (ret && _upb_decode(buf, size, ret, &$1, arena, options))\n" + " ? ret : NULL;\n" + "}\n" "UPB_INLINE char *$0_serialize(const $0 *msg, upb_arena *arena, size_t " "*len) {\n" " return upb_encode(msg, &$1, arena, len);\n"