blob: 8dd0ffc53c9a80a6f2247f5a4777b80636b670b5 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "GPBTestUtilities.h"
#import "google/protobuf/Unittest.pbobjc.h"
#import "google/protobuf/UnittestImport.pbobjc.h"
#import "google/protobuf/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