Skip to content

Commit b375d01

Browse files
Dave MacLachlancopybara-github
authored andcommitted
Optimize startup be reducing selector lookup.
Move away from looking up selectors at proto initialization time to doing optimized string compares at implementation resolving time. PiperOrigin-RevId: 623183331
1 parent e22539b commit b375d01

4 files changed

Lines changed: 266 additions & 122 deletions

File tree

objectivec/GPBDescriptor.m

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -51,40 +51,6 @@ - (instancetype)initWithName:(NSString *)name
5151
static const char kClassNameSuffixKey = 0;
5252
static const char kFileDescriptorCacheKey = 0;
5353

54-
// Utility function to generate selectors on the fly.
55-
static SEL SelFromStrings(const char *prefix, const char *middle, const char *suffix,
56-
BOOL takesArg) {
57-
if (prefix == NULL && suffix == NULL && !takesArg) {
58-
return sel_getUid(middle);
59-
}
60-
const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0;
61-
const size_t middleLen = strlen(middle);
62-
const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0;
63-
size_t totalLen = prefixLen + middleLen + suffixLen + 1; // include space for null on end.
64-
if (takesArg) {
65-
totalLen += 1;
66-
}
67-
char buffer[totalLen];
68-
if (prefix != NULL) {
69-
memcpy(buffer, prefix, prefixLen);
70-
memcpy(buffer + prefixLen, middle, middleLen);
71-
buffer[prefixLen] = (char)toupper(buffer[prefixLen]);
72-
} else {
73-
memcpy(buffer, middle, middleLen);
74-
}
75-
if (suffix != NULL) {
76-
memcpy(buffer + prefixLen + middleLen, suffix, suffixLen);
77-
}
78-
if (takesArg) {
79-
buffer[totalLen - 2] = ':';
80-
}
81-
// Always null terminate it.
82-
buffer[totalLen - 1] = 0;
83-
84-
SEL result = sel_getUid(buffer);
85-
return result;
86-
}
87-
8854
static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageFields)
8955
__attribute__((ns_returns_retained));
9056

@@ -594,8 +560,6 @@ - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields {
594560
for (GPBFieldDescriptor *fieldDesc in fields) {
595561
fieldDesc->containingOneof_ = self;
596562
}
597-
598-
caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO);
599563
}
600564
return self;
601565
}
@@ -682,27 +646,9 @@ - (instancetype)initWithFieldDescription:(void *)description
682646
coreDesc = description;
683647
}
684648
description_ = coreDesc;
685-
getSel_ = sel_getUid(coreDesc->name);
686-
setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES);
687649

688650
GPBDataType dataType = coreDesc->dataType;
689651
BOOL isMessage = GPBDataTypeIsMessage(dataType);
690-
BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
691-
692-
if (isMapOrArray) {
693-
// map<>/repeated fields get a *Count property (inplace of a has*) to
694-
// support checking if there are any entries without triggering
695-
// autocreation.
696-
hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO);
697-
} else {
698-
// It is a single field; it gets has/setHas selectors if...
699-
// - not in a oneof (negative has index)
700-
// - not clearing on zero
701-
if ((coreDesc->hasIndex >= 0) && ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) {
702-
hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO);
703-
setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES);
704-
}
705-
}
706652

707653
// Extra type specific data.
708654
if (isMessage) {
@@ -719,6 +665,7 @@ - (instancetype)initWithFieldDescription:(void *)description
719665
}
720666

721667
// Non map<>/repeated fields can have defaults in proto2 syntax.
668+
BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
722669
if (!isMapOrArray && includesDefault) {
723670
defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue;
724671
if (dataType == GPBDataTypeBytes) {

objectivec/GPBDescriptor_PackagePrivate.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ typedef struct GPBFileDescription {
8080
// Describes a single field in a protobuf as it is represented as an ivar.
8181
typedef struct GPBMessageFieldDescription {
8282
// Name of ivar.
83+
// Note that we looked into using a SEL here instead (which really is just a C string)
84+
// but there is not a way to initialize an SEL with a constant (@selector is not constant) so the
85+
// additional code generated to initialize the value is actually bigger in size than just using a
86+
// C identifier for large apps.
8387
const char *name;
8488
union {
8589
// className is deprecated and will be removed in favor of clazz.
@@ -235,7 +239,6 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
235239
@package
236240
const char *name_;
237241
NSArray *fields_;
238-
SEL caseSel_;
239242
}
240243
// name must be long lived.
241244
- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields;
@@ -245,11 +248,6 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
245248
@package
246249
GPBMessageFieldDescription *description_;
247250
GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
248-
249-
SEL getSel_;
250-
SEL setSel_;
251-
SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise.
252-
SEL setHasSel_;
253251
}
254252
@end
255253

0 commit comments

Comments
 (0)