| // 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 |