| // Protocol Buffers - Google's data interchange format | |
| // Copyright 2013 Google Inc. 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 | |
| #import "GPBTestUtilities.h" | |
| #import "objectivec/Tests/Unittest.pbobjc.h" | |
| #import "objectivec/Tests/UnittestImport.pbobjc.h" | |
| #import "objectivec/Tests/UnittestObjc.pbobjc.h" | |
| // | |
| // This file really just uses the unittests framework as a testbed to | |
| // run some simple performance tests. The data can then be used to help | |
| // evaluate changes to the runtime. | |
| // | |
| static const uint32_t kRepeatedCount = 100; | |
| @interface PerfTests : GPBTestCase | |
| @end | |
| @implementation PerfTests | |
| - (void)setUp { | |
| // A convenient place to put a break point if you want to connect instruments. | |
| [super setUp]; | |
| } | |
| - (void)testMessagePerformance { | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 200; ++i) { | |
| TestAllTypes* message = [[TestAllTypes alloc] init]; | |
| [self setAllFields:message repeatedCount:kRepeatedCount]; | |
| NSData* rawBytes = [message data]; | |
| [message release]; | |
| message = [[TestAllTypes alloc] initWithData:rawBytes error:NULL]; | |
| [message release]; | |
| } | |
| }]; | |
| } | |
| - (void)testMessageSerialParsingPerformance { | |
| // This and the next test are meant to monitor that the parsing functionality of protos does not | |
| // lock across threads when parsing different instances. The Serial version of the test should run | |
| // around ~2 times slower than the Parallel version since it's parsing the protos in the same | |
| // thread. | |
| TestAllTypes* allTypesMessage = [TestAllTypes message]; | |
| [self setAllFields:allTypesMessage repeatedCount:2]; | |
| NSData* allTypesData = allTypesMessage.data; | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 500; ++i) { | |
| [TestAllTypes parseFromData:allTypesData error:NULL]; | |
| [TestAllTypes parseFromData:allTypesData error:NULL]; | |
| } | |
| }]; | |
| } | |
| - (void)testMessageParallelParsingPerformance { | |
| // This and the previous test are meant to monitor that the parsing functionality of protos does | |
| // not lock across threads when parsing different instances. The Serial version of the test should | |
| // run around ~2 times slower than the Parallel version since it's parsing the protos in the same | |
| // thread. | |
| TestAllTypes* allTypesMessage = [TestAllTypes message]; | |
| [self setAllFields:allTypesMessage repeatedCount:2]; | |
| NSData* allTypesData = allTypesMessage.data; | |
| dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT); | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 500; ++i) { | |
| dispatch_group_t group = dispatch_group_create(); | |
| dispatch_group_async(group, concurrentQueue, ^{ | |
| [TestAllTypes parseFromData:allTypesData error:NULL]; | |
| }); | |
| dispatch_group_async(group, concurrentQueue, ^{ | |
| [TestAllTypes parseFromData:allTypesData error:NULL]; | |
| }); | |
| dispatch_group_notify(group, concurrentQueue, | |
| ^{ | |
| }); | |
| dispatch_release(group); | |
| } | |
| }]; | |
| dispatch_release(concurrentQueue); | |
| } | |
| - (void)testMessageSerialExtensionsParsingPerformance { | |
| // This and the next test are meant to monitor that the parsing functionality of protos does not | |
| // lock across threads when parsing different instances when using extensions. The Serial version | |
| // of the test should run around ~2 times slower than the Parallel version since it's parsing the | |
| // protos in the same thread. | |
| TestAllExtensions* allExtensionsMessage = [TestAllExtensions message]; | |
| [self setAllExtensions:allExtensionsMessage repeatedCount:2]; | |
| NSData* allExtensionsData = allExtensionsMessage.data; | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 500; ++i) { | |
| [TestAllExtensions parseFromData:allExtensionsData | |
| extensionRegistry:[self extensionRegistry] | |
| error:NULL]; | |
| [TestAllExtensions parseFromData:allExtensionsData | |
| extensionRegistry:[self extensionRegistry] | |
| error:NULL]; | |
| } | |
| }]; | |
| } | |
| - (void)testMessageParallelExtensionsParsingPerformance { | |
| // This and the previous test are meant to monitor that the parsing functionality of protos does | |
| // not lock across threads when parsing different instances when using extensions. The Serial | |
| // version of the test should run around ~2 times slower than the Parallel version since it's | |
| // parsing the protos in the same thread. | |
| TestAllExtensions* allExtensionsMessage = [TestAllExtensions message]; | |
| [self setAllExtensions:allExtensionsMessage repeatedCount:2]; | |
| NSData* allExtensionsData = allExtensionsMessage.data; | |
| dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT); | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 500; ++i) { | |
| dispatch_group_t group = dispatch_group_create(); | |
| dispatch_group_async(group, concurrentQueue, ^{ | |
| [TestAllExtensions parseFromData:allExtensionsData | |
| extensionRegistry:[UnittestRoot extensionRegistry] | |
| error:NULL]; | |
| }); | |
| dispatch_group_async(group, concurrentQueue, ^{ | |
| [TestAllExtensions parseFromData:allExtensionsData | |
| extensionRegistry:[UnittestRoot extensionRegistry] | |
| error:NULL]; | |
| }); | |
| dispatch_group_notify(group, concurrentQueue, | |
| ^{ | |
| }); | |
| dispatch_release(group); | |
| } | |
| }]; | |
| dispatch_release(concurrentQueue); | |
| } | |
| - (void)testExtensionsPerformance { | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 200; ++i) { | |
| TestAllExtensions* message = [[TestAllExtensions alloc] init]; | |
| [self setAllExtensions:message repeatedCount:kRepeatedCount]; | |
| NSData* rawBytes = [message data]; | |
| [message release]; | |
| TestAllExtensions* message2 = [[TestAllExtensions alloc] initWithData:rawBytes error:NULL]; | |
| [message2 release]; | |
| } | |
| }]; | |
| } | |
| - (void)testPackedTypesPerformance { | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 1000; ++i) { | |
| TestPackedTypes* message = [[TestPackedTypes alloc] init]; | |
| [self setPackedFields:message repeatedCount:kRepeatedCount]; | |
| NSData* rawBytes = [message data]; | |
| [message release]; | |
| message = [[TestPackedTypes alloc] initWithData:rawBytes error:NULL]; | |
| [message release]; | |
| } | |
| }]; | |
| } | |
| - (void)testPackedExtensionsPerformance { | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 1000; ++i) { | |
| TestPackedExtensions* message = [[TestPackedExtensions alloc] init]; | |
| [self setPackedExtensions:message repeatedCount:kRepeatedCount]; | |
| NSData* rawBytes = [message data]; | |
| [message release]; | |
| TestPackedExtensions* message2 = [[TestPackedExtensions alloc] initWithData:rawBytes | |
| error:NULL]; | |
| [message2 release]; | |
| } | |
| }]; | |
| } | |
| - (void)testHas { | |
| TestAllTypes* message = [self allSetRepeatedCount:1]; | |
| [self measureBlock:^{ | |
| for (int i = 0; i < 10000; ++i) { | |
| [message hasOptionalInt32]; | |
| message.hasOptionalInt32 = NO; | |
| [message hasOptionalInt32]; | |
| [message hasOptionalInt64]; | |
| message.hasOptionalInt64 = NO; | |
| [message hasOptionalInt64]; | |
| [message hasOptionalUint32]; | |
| message.hasOptionalUint32 = NO; | |
| [message hasOptionalUint32]; | |
| [message hasOptionalUint64]; | |
| message.hasOptionalUint64 = NO; | |
| [message hasOptionalUint64]; | |
| [message hasOptionalSint32]; | |
| message.hasOptionalSint32 = NO; | |
| [message hasOptionalSint32]; | |
| [message hasOptionalSint64]; | |
| message.hasOptionalSint64 = NO; | |
| [message hasOptionalSint64]; | |
| [message hasOptionalFixed32]; | |
| message.hasOptionalFixed32 = NO; | |
| [message hasOptionalFixed32]; | |
| [message hasOptionalFixed64]; | |
| message.hasOptionalFixed64 = NO; | |
| [message hasOptionalFixed64]; | |
| [message hasOptionalSfixed32]; | |
| message.hasOptionalSfixed32 = NO; | |
| [message hasOptionalSfixed32]; | |
| [message hasOptionalSfixed64]; | |
| message.hasOptionalSfixed64 = NO; | |
| [message hasOptionalSfixed64]; | |
| [message hasOptionalFloat]; | |
| message.hasOptionalFloat = NO; | |
| [message hasOptionalFloat]; | |
| [message hasOptionalDouble]; | |
| message.hasOptionalDouble = NO; | |
| [message hasOptionalDouble]; | |
| [message hasOptionalBool]; | |
| message.hasOptionalBool = NO; | |
| [message hasOptionalBool]; | |
| [message hasOptionalString]; | |
| message.hasOptionalString = NO; | |
| [message hasOptionalString]; | |
| [message hasOptionalBytes]; | |
| message.hasOptionalBytes = NO; | |
| [message hasOptionalBytes]; | |
| [message hasOptionalGroup]; | |
| message.hasOptionalGroup = NO; | |
| [message hasOptionalGroup]; | |
| [message hasOptionalNestedMessage]; | |
| message.hasOptionalNestedMessage = NO; | |
| [message hasOptionalNestedMessage]; | |
| [message hasOptionalForeignMessage]; | |
| message.hasOptionalForeignMessage = NO; | |
| [message hasOptionalForeignMessage]; | |
| [message hasOptionalImportMessage]; | |
| message.hasOptionalImportMessage = NO; | |
| [message hasOptionalImportMessage]; | |
| [message.optionalGroup hasA]; | |
| message.optionalGroup.hasA = NO; | |
| [message.optionalGroup hasA]; | |
| [message.optionalNestedMessage hasBb]; | |
| message.optionalNestedMessage.hasBb = NO; | |
| [message.optionalNestedMessage hasBb]; | |
| [message.optionalForeignMessage hasC]; | |
| message.optionalForeignMessage.hasC = NO; | |
| [message.optionalForeignMessage hasC]; | |
| [message.optionalImportMessage hasD]; | |
| message.optionalImportMessage.hasD = NO; | |
| [message.optionalImportMessage hasD]; | |
| [message hasOptionalNestedEnum]; | |
| message.hasOptionalNestedEnum = NO; | |
| [message hasOptionalNestedEnum]; | |
| [message hasOptionalForeignEnum]; | |
| message.hasOptionalForeignEnum = NO; | |
| [message hasOptionalForeignEnum]; | |
| [message hasOptionalImportEnum]; | |
| message.hasOptionalImportEnum = NO; | |
| [message hasOptionalImportEnum]; | |
| [message hasOptionalStringPiece]; | |
| message.hasOptionalStringPiece = NO; | |
| [message hasOptionalStringPiece]; | |
| [message hasOptionalCord]; | |
| message.hasOptionalCord = NO; | |
| [message hasOptionalCord]; | |
| [message hasDefaultInt32]; | |
| message.hasDefaultInt32 = NO; | |
| [message hasDefaultInt32]; | |
| [message hasDefaultInt64]; | |
| message.hasDefaultInt64 = NO; | |
| [message hasDefaultInt64]; | |
| [message hasDefaultUint32]; | |
| message.hasDefaultUint32 = NO; | |
| [message hasDefaultUint32]; | |
| [message hasDefaultUint64]; | |
| message.hasDefaultUint64 = NO; | |
| [message hasDefaultUint64]; | |
| [message hasDefaultSint32]; | |
| message.hasDefaultSint32 = NO; | |
| [message hasDefaultSint32]; | |
| [message hasDefaultSint64]; | |
| message.hasDefaultSint64 = NO; | |
| [message hasDefaultSint64]; | |
| [message hasDefaultFixed32]; | |
| message.hasDefaultFixed32 = NO; | |
| [message hasDefaultFixed32]; | |
| [message hasDefaultFixed64]; | |
| message.hasDefaultFixed64 = NO; | |
| [message hasDefaultFixed64]; | |
| [message hasDefaultSfixed32]; | |
| message.hasDefaultSfixed32 = NO; | |
| [message hasDefaultSfixed32]; | |
| [message hasDefaultSfixed64]; | |
| message.hasDefaultSfixed64 = NO; | |
| [message hasDefaultSfixed64]; | |
| [message hasDefaultFloat]; | |
| message.hasDefaultFloat = NO; | |
| [message hasDefaultFloat]; | |
| [message hasDefaultDouble]; | |
| message.hasDefaultDouble = NO; | |
| [message hasDefaultDouble]; | |
| [message hasDefaultBool]; | |
| message.hasDefaultBool = NO; | |
| [message hasDefaultBool]; | |
| [message hasDefaultString]; | |
| message.hasDefaultString = NO; | |
| [message hasDefaultString]; | |
| [message hasDefaultBytes]; | |
| message.hasDefaultBytes = NO; | |
| [message hasDefaultBytes]; | |
| [message hasDefaultNestedEnum]; | |
| message.hasDefaultNestedEnum = NO; | |
| [message hasDefaultNestedEnum]; | |
| [message hasDefaultForeignEnum]; | |
| message.hasDefaultForeignEnum = NO; | |
| [message hasDefaultForeignEnum]; | |
| [message hasDefaultImportEnum]; | |
| message.hasDefaultImportEnum = NO; | |
| [message hasDefaultImportEnum]; | |
| [message hasDefaultStringPiece]; | |
| message.hasDefaultStringPiece = NO; | |
| [message hasDefaultStringPiece]; | |
| [message hasDefaultCord]; | |
| message.hasDefaultCord = NO; | |
| [message hasDefaultCord]; | |
| } | |
| }]; | |
| } | |
| @end |