blob: 8dd0ffc53c9a80a6f2247f5a4777b80636b670b5 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// Protocol Buffers - Google's data interchange format
2// Copyright 2013 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "GPBTestUtilities.h"
32#import "google/protobuf/Unittest.pbobjc.h"
33#import "google/protobuf/UnittestImport.pbobjc.h"
34#import "google/protobuf/UnittestObjc.pbobjc.h"
35
36//
37// This file really just uses the unittests framework as a testbed to
38// run some simple performance tests. The data can then be used to help
39// evaluate changes to the runtime.
40//
41
42static const uint32_t kRepeatedCount = 100;
43
44@interface PerfTests : GPBTestCase
45@end
46
47@implementation PerfTests
48
49- (void)setUp {
50 // A convenient place to put a break point if you want to connect instruments.
51 [super setUp];
52}
53
54- (void)testMessagePerformance {
55 [self measureBlock:^{
56 for (int i = 0; i < 200; ++i) {
57 TestAllTypes* message = [[TestAllTypes alloc] init];
58 [self setAllFields:message repeatedCount:kRepeatedCount];
59 NSData* rawBytes = [message data];
60 [message release];
61 message = [[TestAllTypes alloc] initWithData:rawBytes error:NULL];
62 [message release];
63 }
64 }];
65}
66
Austin Schuh40c16522018-10-28 20:27:54 -070067- (void)testMessageSerialParsingPerformance {
68 // This and the next test are meant to monitor that the parsing functionality of protos does not
69 // lock across threads when parsing different instances. The Serial version of the test should run
70 // around ~2 times slower than the Parallel version since it's parsing the protos in the same
71 // thread.
72 TestAllTypes *allTypesMessage = [TestAllTypes message];
73 [self setAllFields:allTypesMessage repeatedCount:2];
74 NSData *allTypesData = allTypesMessage.data;
75
76 [self measureBlock:^{
77 for (int i = 0; i < 500; ++i) {
78 [TestAllTypes parseFromData:allTypesData error:NULL];
79 [TestAllTypes parseFromData:allTypesData error:NULL];
80 }
81 }];
82}
83
84- (void)testMessageParallelParsingPerformance {
85 // This and the previous test are meant to monitor that the parsing functionality of protos does
86 // not lock across threads when parsing different instances. The Serial version of the test should
87 // run around ~2 times slower than the Parallel version since it's parsing the protos in the same
88 // thread.
89 TestAllTypes *allTypesMessage = [TestAllTypes message];
90 [self setAllFields:allTypesMessage repeatedCount:2];
91 NSData *allTypesData = allTypesMessage.data;
92
93 dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT);
94
95 [self measureBlock:^{
96 for (int i = 0; i < 500; ++i) {
97 dispatch_group_t group = dispatch_group_create();
98
99 dispatch_group_async(group, concurrentQueue, ^{
100 [TestAllTypes parseFromData:allTypesData error:NULL];
101 });
102
103 dispatch_group_async(group, concurrentQueue, ^{
104 [TestAllTypes parseFromData:allTypesData error:NULL];
105 });
106
107 dispatch_group_notify(group, concurrentQueue, ^{});
108
109 dispatch_release(group);
110 }
111 }];
112
113 dispatch_release(concurrentQueue);
114}
115
116- (void)testMessageSerialExtensionsParsingPerformance {
117 // This and the next test are meant to monitor that the parsing functionality of protos does not
118 // lock across threads when parsing different instances when using extensions. The Serial version
119 // of the test should run around ~2 times slower than the Parallel version since it's parsing the
120 // protos in the same thread.
121 TestAllExtensions *allExtensionsMessage = [TestAllExtensions message];
122 [self setAllExtensions:allExtensionsMessage repeatedCount:2];
123 NSData *allExtensionsData = allExtensionsMessage.data;
124
125 [self measureBlock:^{
126 for (int i = 0; i < 500; ++i) {
127 [TestAllExtensions parseFromData:allExtensionsData
128 extensionRegistry:[self extensionRegistry]
129 error:NULL];
130 [TestAllExtensions parseFromData:allExtensionsData
131 extensionRegistry:[self extensionRegistry]
132 error:NULL];
133 }
134 }];
135}
136
137- (void)testMessageParallelExtensionsParsingPerformance {
138 // This and the previous test are meant to monitor that the parsing functionality of protos does
139 // not lock across threads when parsing different instances when using extensions. The Serial
140 // version of the test should run around ~2 times slower than the Parallel version since it's
141 // parsing the protos in the same thread.
142 TestAllExtensions *allExtensionsMessage = [TestAllExtensions message];
143 [self setAllExtensions:allExtensionsMessage repeatedCount:2];
144 NSData *allExtensionsData = allExtensionsMessage.data;
145
146 dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT);
147
148 [self measureBlock:^{
149 for (int i = 0; i < 500; ++i) {
150 dispatch_group_t group = dispatch_group_create();
151
152 dispatch_group_async(group, concurrentQueue, ^{
153 [TestAllExtensions parseFromData:allExtensionsData
154 extensionRegistry:[UnittestRoot extensionRegistry]
155 error:NULL];
156 });
157
158 dispatch_group_async(group, concurrentQueue, ^{
159 [TestAllExtensions parseFromData:allExtensionsData
160 extensionRegistry:[UnittestRoot extensionRegistry]
161 error:NULL];
162 });
163
164 dispatch_group_notify(group, concurrentQueue, ^{});
165
166 dispatch_release(group);
167 }
168 }];
169
170 dispatch_release(concurrentQueue);
171}
172
Brian Silverman9c614bc2016-02-15 20:20:02 -0500173- (void)testExtensionsPerformance {
174 [self measureBlock:^{
175 for (int i = 0; i < 200; ++i) {
176 TestAllExtensions* message = [[TestAllExtensions alloc] init];
177 [self setAllExtensions:message repeatedCount:kRepeatedCount];
178 NSData* rawBytes = [message data];
179 [message release];
180 TestAllExtensions* message2 =
181 [[TestAllExtensions alloc] initWithData:rawBytes error:NULL];
182 [message2 release];
183 }
184 }];
185}
186
187- (void)testPackedTypesPerformance {
188 [self measureBlock:^{
189 for (int i = 0; i < 1000; ++i) {
190 TestPackedTypes* message = [[TestPackedTypes alloc] init];
191 [self setPackedFields:message repeatedCount:kRepeatedCount];
192 NSData* rawBytes = [message data];
193 [message release];
194 message = [[TestPackedTypes alloc] initWithData:rawBytes error:NULL];
195 [message release];
196 }
197 }];
198}
199
200- (void)testPackedExtensionsPerformance {
201 [self measureBlock:^{
202 for (int i = 0; i < 1000; ++i) {
203 TestPackedExtensions* message = [[TestPackedExtensions alloc] init];
204 [self setPackedExtensions:message repeatedCount:kRepeatedCount];
205 NSData* rawBytes = [message data];
206 [message release];
207 TestPackedExtensions* message2 =
208 [[TestPackedExtensions alloc] initWithData:rawBytes error:NULL];
209 [message2 release];
210 }
211 }];
212}
213
214- (void)testHas {
215 TestAllTypes* message = [self allSetRepeatedCount:1];
216 [self measureBlock:^{
217 for (int i = 0; i < 10000; ++i) {
218 [message hasOptionalInt32];
219 message.hasOptionalInt32 = NO;
220 [message hasOptionalInt32];
221
222 [message hasOptionalInt64];
223 message.hasOptionalInt64 = NO;
224 [message hasOptionalInt64];
225
226 [message hasOptionalUint32];
227 message.hasOptionalUint32 = NO;
228 [message hasOptionalUint32];
229
230 [message hasOptionalUint64];
231 message.hasOptionalUint64 = NO;
232 [message hasOptionalUint64];
233
234 [message hasOptionalSint32];
235 message.hasOptionalSint32 = NO;
236 [message hasOptionalSint32];
237
238 [message hasOptionalSint64];
239 message.hasOptionalSint64 = NO;
240 [message hasOptionalSint64];
241
242 [message hasOptionalFixed32];
243 message.hasOptionalFixed32 = NO;
244 [message hasOptionalFixed32];
245
246 [message hasOptionalFixed64];
247 message.hasOptionalFixed64 = NO;
248 [message hasOptionalFixed64];
249
250 [message hasOptionalSfixed32];
251 message.hasOptionalSfixed32 = NO;
252 [message hasOptionalSfixed32];
253
254 [message hasOptionalSfixed64];
255 message.hasOptionalSfixed64 = NO;
256 [message hasOptionalSfixed64];
257
258 [message hasOptionalFloat];
259 message.hasOptionalFloat = NO;
260 [message hasOptionalFloat];
261
262 [message hasOptionalDouble];
263 message.hasOptionalDouble = NO;
264 [message hasOptionalDouble];
265
266 [message hasOptionalBool];
267 message.hasOptionalBool = NO;
268 [message hasOptionalBool];
269
270 [message hasOptionalString];
271 message.hasOptionalString = NO;
272 [message hasOptionalString];
273
274 [message hasOptionalBytes];
275 message.hasOptionalBytes = NO;
276 [message hasOptionalBytes];
277
278 [message hasOptionalGroup];
279 message.hasOptionalGroup = NO;
280 [message hasOptionalGroup];
281
282 [message hasOptionalNestedMessage];
283 message.hasOptionalNestedMessage = NO;
284 [message hasOptionalNestedMessage];
285
286 [message hasOptionalForeignMessage];
287 message.hasOptionalForeignMessage = NO;
288 [message hasOptionalForeignMessage];
289
290 [message hasOptionalImportMessage];
291 message.hasOptionalImportMessage = NO;
292 [message hasOptionalImportMessage];
293
294 [message.optionalGroup hasA];
295 message.optionalGroup.hasA = NO;
296 [message.optionalGroup hasA];
297
298 [message.optionalNestedMessage hasBb];
299 message.optionalNestedMessage.hasBb = NO;
300 [message.optionalNestedMessage hasBb];
301
302 [message.optionalForeignMessage hasC];
303 message.optionalForeignMessage.hasC = NO;
304 [message.optionalForeignMessage hasC];
305
306 [message.optionalImportMessage hasD];
307 message.optionalImportMessage.hasD = NO;
308 [message.optionalImportMessage hasD];
309
310 [message hasOptionalNestedEnum];
311 message.hasOptionalNestedEnum = NO;
312 [message hasOptionalNestedEnum];
313
314 [message hasOptionalForeignEnum];
315 message.hasOptionalForeignEnum = NO;
316 [message hasOptionalForeignEnum];
317
318 [message hasOptionalImportEnum];
319 message.hasOptionalImportEnum = NO;
320 [message hasOptionalImportEnum];
321
322 [message hasOptionalStringPiece];
323 message.hasOptionalStringPiece = NO;
324 [message hasOptionalStringPiece];
325
326 [message hasOptionalCord];
327 message.hasOptionalCord = NO;
328 [message hasOptionalCord];
329
330 [message hasDefaultInt32];
331 message.hasDefaultInt32 = NO;
332 [message hasDefaultInt32];
333
334 [message hasDefaultInt64];
335 message.hasDefaultInt64 = NO;
336 [message hasDefaultInt64];
337
338 [message hasDefaultUint32];
339 message.hasDefaultUint32 = NO;
340 [message hasDefaultUint32];
341
342 [message hasDefaultUint64];
343 message.hasDefaultUint64 = NO;
344 [message hasDefaultUint64];
345
346 [message hasDefaultSint32];
347 message.hasDefaultSint32 = NO;
348 [message hasDefaultSint32];
349
350 [message hasDefaultSint64];
351 message.hasDefaultSint64 = NO;
352 [message hasDefaultSint64];
353
354 [message hasDefaultFixed32];
355 message.hasDefaultFixed32 = NO;
356 [message hasDefaultFixed32];
357
358 [message hasDefaultFixed64];
359 message.hasDefaultFixed64 = NO;
360 [message hasDefaultFixed64];
361
362 [message hasDefaultSfixed32];
363 message.hasDefaultSfixed32 = NO;
364 [message hasDefaultSfixed32];
365
366 [message hasDefaultSfixed64];
367 message.hasDefaultSfixed64 = NO;
368 [message hasDefaultSfixed64];
369
370 [message hasDefaultFloat];
371 message.hasDefaultFloat = NO;
372 [message hasDefaultFloat];
373
374 [message hasDefaultDouble];
375 message.hasDefaultDouble = NO;
376 [message hasDefaultDouble];
377
378 [message hasDefaultBool];
379 message.hasDefaultBool = NO;
380 [message hasDefaultBool];
381
382 [message hasDefaultString];
383 message.hasDefaultString = NO;
384 [message hasDefaultString];
385
386 [message hasDefaultBytes];
387 message.hasDefaultBytes = NO;
388 [message hasDefaultBytes];
389
390 [message hasDefaultNestedEnum];
391 message.hasDefaultNestedEnum = NO;
392 [message hasDefaultNestedEnum];
393
394 [message hasDefaultForeignEnum];
395 message.hasDefaultForeignEnum = NO;
396 [message hasDefaultForeignEnum];
397
398 [message hasDefaultImportEnum];
399 message.hasDefaultImportEnum = NO;
400 [message hasDefaultImportEnum];
401
402 [message hasDefaultStringPiece];
403 message.hasDefaultStringPiece = NO;
404 [message hasDefaultStringPiece];
405
406 [message hasDefaultCord];
407 message.hasDefaultCord = NO;
408 [message hasDefaultCord];
409 }
410 }];
411}
412
413@end