• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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
67- (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
173- (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
414