Protocol Buffers - Google's data interchange format (grpc依赖) https://developers.google.com/protocol-buffers/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
7.8 KiB

// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "upb/reflection/message.h"
#include <stdint.h>
#include <string.h>
#include "upb/mem/arena.h"
#include "upb/message/accessors.h"
#include "upb/message/array.h"
#include "upb/message/internal/extension.h"
#include "upb/message/internal/message.h"
#include "upb/message/map.h"
#include "upb/message/message.h"
#include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
#include "upb/mini_table/internal/message.h"
#include "upb/mini_table/message.h"
#include "upb/reflection/def.h"
#include "upb/reflection/def_pool.h"
#include "upb/reflection/message_def.h"
#include "upb/reflection/oneof_def.h"
// Must be last.
#include "upb/port/def.inc"
bool upb_Message_HasFieldByDef(const upb_Message* msg, const upb_FieldDef* f) {
const upb_MiniTableField* m_f = upb_FieldDef_MiniTable(f);
UPB_ASSERT(upb_FieldDef_HasPresence(f));
if (upb_MiniTableField_IsExtension(m_f)) {
return upb_Message_HasExtension(msg, (const upb_MiniTableExtension*)m_f);
} else {
return upb_Message_HasBaseField(msg, m_f);
}
}
const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg,
const upb_OneofDef* o) {
const upb_FieldDef* f = upb_OneofDef_Field(o, 0);
if (upb_OneofDef_IsSynthetic(o)) {
UPB_ASSERT(upb_OneofDef_FieldCount(o) == 1);
return upb_Message_HasFieldByDef(msg, f) ? f : NULL;
} else {
const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
uint32_t oneof_case = upb_Message_WhichOneofFieldNumber(msg, field);
f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
UPB_ASSERT((f != NULL) == (oneof_case != 0));
return f;
}
}
upb_MessageValue upb_Message_GetFieldByDef(const upb_Message* msg,
const upb_FieldDef* f) {
Refactored message accessors to share a common set of functions instead of duplicating logic. Prior to this CL, there were several different code paths for reading/writing message data. Generated code, MiniTable accessors, and reflection all performed direct manipulation of the bits and bytes in a message, but they all had distinct implementations that did not share much of any code. This divergence meant that they could easily have different behavior, bugs could creep into one but not another, and we would need three different sets of tests to get full test coverage. This also made it very difficult to change the internal representation in any way, since it would require updating many places in the code. With this CL, the three different APIs for accessing message data now all share a common set of functions. The common functions all take a `upb_MiniTableField` as the canonical description of a field's type and layout. The lowest-level functions are very branchy, as they must test for every possible variation in the field type (field vs oneof, hasbit vs no-hasbit, different field sizes, whether a nonzero default value exists, extension vs. regular field), however these functions are declared inline and designed to be very optimizable when values are known at compile time. In generated accessors, for example, we can declare constant `upb_MiniTableField` instances so that all values can constant-propagate, and we can get fully specialized code even though we are calling a generic function. On the other hand, when we use the generic functions from reflection, we get runtime branches since values are not known at compile time. But even the function is written to still be as efficient as possible even when used from reflection. For example, we use memcpy() calls with constant length so that the compiler can optimize these into inline loads/stores without having to make an out-of-line call to memcpy(). In this way, this CL should be a benefit to both correctness and performance. It will also make it easier to change the message representation, for example to optimize the encoder by giving hasbits to all fields. Note that we have not completely consolidated all access in this CL: 1. Some functions outside of get/set such as clear and hazzers are not yet unified. 2. The encoder and decoder still touch the message without going through the common functions. The encoder and decoder require a bit more specialized code to get good performance when reading/writing fields en masse. PiperOrigin-RevId: 490016095
2 years ago
upb_MessageValue default_val = upb_FieldDef_Default(f);
return upb_Message_GetField(msg, upb_FieldDef_MiniTable(f), default_val);
}
upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
const upb_FieldDef* f,
upb_Arena* a) {
UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
if (upb_FieldDef_HasPresence(f) && !upb_Message_HasFieldByDef(msg, f)) {
// We need to skip the upb_Message_GetFieldByDef() call in this case.
goto make;
}
upb_MessageValue val = upb_Message_GetFieldByDef(msg, f);
if (val.array_val) {
return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
}
upb_MutableMessageValue ret;
make:
if (!a) return (upb_MutableMessageValue){.array = NULL};
if (upb_FieldDef_IsMap(f)) {
const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
const upb_FieldDef* key =
upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
const upb_FieldDef* value =
upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
ret.map =
upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
} else if (upb_FieldDef_IsRepeated(f)) {
ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
} else {
UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
ret.msg = upb_Message_New(upb_MessageDef_MiniTable(m), a);
}
val.array_val = ret.array;
upb_Message_SetFieldByDef(msg, f, val, a);
return ret;
}
bool upb_Message_SetFieldByDef(upb_Message* msg, const upb_FieldDef* f,
upb_MessageValue val, upb_Arena* a) {
return upb_Message_SetField(msg, upb_FieldDef_MiniTable(f), val, a);
}
void upb_Message_ClearFieldByDef(upb_Message* msg, const upb_FieldDef* f) {
const upb_MiniTableField* m_f = upb_FieldDef_MiniTable(f);
if (upb_MiniTableField_IsExtension(m_f)) {
upb_Message_ClearExtension(msg, (const upb_MiniTableExtension*)m_f);
} else {
upb_Message_ClearBaseField(msg, m_f);
}
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
}
void upb_Message_ClearByDef(upb_Message* msg, const upb_MessageDef* m) {
upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
}
bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
upb_MessageValue* out_val, size_t* iter) {
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
const upb_MiniTable* mt = upb_MessageDef_MiniTable(m);
size_t i = *iter;
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
size_t n = upb_MiniTable_FieldCount(mt);
const upb_MessageValue zero = {0};
UPB_UNUSED(ext_pool);
// Iterate over normal fields, returning the first one that is set.
while (++i < n) {
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
const upb_MiniTableField* field = upb_MiniTable_GetFieldByIndex(mt, i);
upb_MessageValue val = upb_Message_GetField(msg, field, zero);
// Skip field if unset or empty.
if (upb_MiniTableField_HasPresence(field)) {
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
if (!upb_Message_HasBaseField(msg, field)) continue;
} else {
switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(field)) {
case kUpb_FieldMode_Map:
if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
break;
case kUpb_FieldMode_Array:
if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
break;
case kUpb_FieldMode_Scalar:
if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, &val))
continue;
break;
5 years ago
}
}
*out_val = val;
Print non-extension fields by field number order instead of .proto file order. This will affect both JSON and TextFormat. The serialization order for these two formats is not specified, so switching from `.proto` file order to field number order should not be breaking. This does not affect the order of extensions, which are always printed last (even if their field numbers interleave with regular fields. This change appears to speed up JSON encoding by about 15%: ``` name old speed new speed delta BM_LoadAdsDescriptor_Upb<NoLayout> 132MB/s ± 2% 129MB/s ±11% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Upb<WithLayout> 118MB/s ± 1% 118MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<NoLayout> 62.3MB/s ± 2% 62.4MB/s ± 2% ~ (p=0.841 n=5+5) BM_LoadAdsDescriptor_Proto2<WithLayout> 61.0MB/s ± 2% 60.1MB/s ± 8% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Copy> 566MB/s ± 1% 572MB/s ± 2% ~ (p=0.222 n=5+5) BM_Parse_Upb_FileDesc<UseArena, Alias> 626MB/s ± 1% 620MB/s ± 3% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Copy> 572MB/s ± 1% 578MB/s ± 2% ~ (p=0.421 n=5+5) BM_Parse_Upb_FileDesc<InitBlock, Alias> 636MB/s ± 1% 635MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, NoArena, Copy> 360MB/s ±12% 345MB/s ±14% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDesc, UseArena, Copy> 692MB/s ± 2% 691MB/s ± 4% ~ (p=0.548 n=5+5) BM_Parse_Proto2<FileDesc, InitBlock, Copy> 709MB/s ± 1% 705MB/s ± 2% ~ (p=0.841 n=5+5) BM_Parse_Proto2<FileDescSV, InitBlock, Alias> 642MB/s ± 1% 646MB/s ± 1% ~ (p=0.690 n=5+5) BM_SerializeDescriptor_Proto2 1.19GB/s ± 8% 1.22GB/s ± 8% ~ (p=0.095 n=5+5) BM_SerializeDescriptor_Upb 725MB/s ± 1% 732MB/s ± 1% ~ (p=0.056 n=5+5) BM_JsonParse_Upb 187MB/s ± 1% 188MB/s ± 2% ~ (p=1.000 n=5+4) BM_JsonParse_Proto2 18.7MB/s ± 1% 18.6MB/s ± 2% ~ (p=0.841 n=5+5) BM_JsonSerialize_Upb 106MB/s ± 1% 122MB/s ± 1% +14.65% (p=0.008 n=5+5) BM_JsonSerialize_Proto2 54.0MB/s ± 2% 53.9MB/s ± 3% ~ (p=1.000 n=5+5) ``` PiperOrigin-RevId: 619004014
8 months ago
*out_f =
upb_MessageDef_FindFieldByNumber(m, upb_MiniTableField_Number(field));
*iter = i;
return true;
}
if (ext_pool) {
// Return any extensions that are set.
size_t count;
const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count);
if (i - n < count) {
ext += count - 1 - (i - n);
memcpy(out_val, &ext->data, sizeof(*out_val));
*out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
*iter = i;
return true;
}
}
*iter = i;
return false;
}
bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
int depth) {
size_t iter = kUpb_Message_Begin;
const upb_FieldDef* f;
upb_MessageValue val;
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
bool ret = true;
if (--depth == 0) return false;
_upb_Message_DiscardUnknown_shallow(msg);
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
if (!subm) continue;
if (upb_FieldDef_IsMap(f)) {
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
upb_Map* map = (upb_Map*)val.map_val;
size_t iter = kUpb_Map_Begin;
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
if (!val_m) continue;
upb_MessageValue map_key, map_val;
while (upb_Map_Next(map, &map_key, &map_val, &iter)) {
if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
depth)) {
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
ret = false;
}
}
} else if (upb_FieldDef_IsRepeated(f)) {
const upb_Array* arr = val.array_val;
size_t i, n = upb_Array_Size(arr);
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
for (i = 0; i < n; i++) {
upb_MessageValue elem = upb_Array_Get(arr, i);
if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
depth)) {
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
ret = false;
}
}
} else {
if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
depth)) {
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
ret = false;
}
}
}
return ret;
}
bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
int maxdepth) {
return _upb_Message_DiscardUnknown(msg, m, maxdepth);
Fixes for PHP. (#286) - A new PHP-specific upb amalgamation. It contains everything related to upb_msg, but leaves out all of the old handlers-related interfaces and encoders/decoders. # Schema/Defs Changes - Changed `upb_fielddef_msgsubdef()` and `upb_fielddef_enumsubdef()` to return `NULL` instead of assert-failing if the field is not a message or enum. - Added `upb_msgdef_iswrapper()`, to test whether this is a wrapper well-known type. # Decoder - Decoder bugfix: when we parse a submessage inside a oneof, we need to clear out any previous data, so we don't misinterpret it as a pointer to an existing submessage. # JSON Decoder - Allowed well-known types at the top level to have their special processing. - Fixed a bug that could occur when parsing nested empty lists/objects, eg `[[]]`. - Made the "ignore unknown" option also be permissive about unknown enumerators by setting them to 0. # JSON Encoder - Allowed well-known types at the top level to have their special processing. - Removed all spaces after `:` and `,` characters, to match the old encoder and pass goldenfile tests. # Message / Reflection - Changed `upb_msg_hasoneof()` -> `upb_msg_whichoneof()`. The new function returns the `upb_fielddef*` of whichever oneof is set. - Implemented `upb_msg_clearfield()` and added/implemented `upb_msg_clear()`. - Added `upb_msg_discardunknown()`. Part of me thinks this should go in a util library instead of core reflection since it is a recursive algorithm. # Compiler - Always emit descriptors as an array instead of as a string, to avoid exceeding maximum string lengths. If this becomes a speed issue later we can go back to two separate paths.
5 years ago
}