1// Protocol Buffers - Google's data interchange format 2// Copyright 2013 Google Inc. All rights reserved. 3// 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file or at 6// https://developers.google.com/open-source/licenses/bsd 7 8#import "GPBTestUtilities.h" 9#import "objectivec/Tests/Unittest.pbobjc.h" 10#import "objectivec/Tests/UnittestImport.pbobjc.h" 11#import "objectivec/Tests/UnittestObjc.pbobjc.h" 12 13// 14// This file really just uses the unittests framework as a testbed to 15// run some simple performance tests. The data can then be used to help 16// evaluate changes to the runtime. 17// 18 19static const uint32_t kRepeatedCount = 100; 20 21@interface PerfTests : GPBTestCase 22@end 23 24@implementation PerfTests 25 26- (void)setUp { 27 // A convenient place to put a break point if you want to connect instruments. 28 [super setUp]; 29} 30 31- (void)testMessagePerformance { 32 [self measureBlock:^{ 33 for (int i = 0; i < 200; ++i) { 34 TestAllTypes* message = [[TestAllTypes alloc] init]; 35 [self setAllFields:message repeatedCount:kRepeatedCount]; 36 NSData* rawBytes = [message data]; 37 [message release]; 38 message = [[TestAllTypes alloc] initWithData:rawBytes error:NULL]; 39 [message release]; 40 } 41 }]; 42} 43 44- (void)testMessageSerialParsingPerformance { 45 // This and the next test are meant to monitor that the parsing functionality of protos does not 46 // lock across threads when parsing different instances. The Serial version of the test should run 47 // around ~2 times slower than the Parallel version since it's parsing the protos in the same 48 // thread. 49 TestAllTypes* allTypesMessage = [TestAllTypes message]; 50 [self setAllFields:allTypesMessage repeatedCount:2]; 51 NSData* allTypesData = allTypesMessage.data; 52 53 [self measureBlock:^{ 54 for (int i = 0; i < 500; ++i) { 55 [TestAllTypes parseFromData:allTypesData error:NULL]; 56 [TestAllTypes parseFromData:allTypesData error:NULL]; 57 } 58 }]; 59} 60 61- (void)testMessageParallelParsingPerformance { 62 // This and the previous test are meant to monitor that the parsing functionality of protos does 63 // not lock across threads when parsing different instances. The Serial version of the test should 64 // run around ~2 times slower than the Parallel version since it's parsing the protos in the same 65 // thread. 66 TestAllTypes* allTypesMessage = [TestAllTypes message]; 67 [self setAllFields:allTypesMessage repeatedCount:2]; 68 NSData* allTypesData = allTypesMessage.data; 69 70 dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT); 71 72 [self measureBlock:^{ 73 for (int i = 0; i < 500; ++i) { 74 dispatch_group_t group = dispatch_group_create(); 75 76 dispatch_group_async(group, concurrentQueue, ^{ 77 [TestAllTypes parseFromData:allTypesData error:NULL]; 78 }); 79 80 dispatch_group_async(group, concurrentQueue, ^{ 81 [TestAllTypes parseFromData:allTypesData error:NULL]; 82 }); 83 84 dispatch_group_notify(group, concurrentQueue, 85 ^{ 86 }); 87 88 dispatch_release(group); 89 } 90 }]; 91 92 dispatch_release(concurrentQueue); 93} 94 95- (void)testMessageSerialExtensionsParsingPerformance { 96 // This and the next test are meant to monitor that the parsing functionality of protos does not 97 // lock across threads when parsing different instances when using extensions. The Serial version 98 // of the test should run around ~2 times slower than the Parallel version since it's parsing the 99 // protos in the same thread. 100 TestAllExtensions* allExtensionsMessage = [TestAllExtensions message]; 101 [self setAllExtensions:allExtensionsMessage repeatedCount:2]; 102 NSData* allExtensionsData = allExtensionsMessage.data; 103 104 [self measureBlock:^{ 105 for (int i = 0; i < 500; ++i) { 106 [TestAllExtensions parseFromData:allExtensionsData 107 extensionRegistry:[self extensionRegistry] 108 error:NULL]; 109 [TestAllExtensions parseFromData:allExtensionsData 110 extensionRegistry:[self extensionRegistry] 111 error:NULL]; 112 } 113 }]; 114} 115 116- (void)testMessageParallelExtensionsParsingPerformance { 117 // This and the previous test are meant to monitor that the parsing functionality of protos does 118 // not lock across threads when parsing different instances when using extensions. The Serial 119 // version of the test should run around ~2 times slower than the Parallel version since it's 120 // parsing the protos in the same thread. 121 TestAllExtensions* allExtensionsMessage = [TestAllExtensions message]; 122 [self setAllExtensions:allExtensionsMessage repeatedCount:2]; 123 NSData* allExtensionsData = allExtensionsMessage.data; 124 125 dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT); 126 127 [self measureBlock:^{ 128 for (int i = 0; i < 500; ++i) { 129 dispatch_group_t group = dispatch_group_create(); 130 131 dispatch_group_async(group, concurrentQueue, ^{ 132 [TestAllExtensions parseFromData:allExtensionsData 133 extensionRegistry:[UnittestRoot extensionRegistry] 134 error:NULL]; 135 }); 136 137 dispatch_group_async(group, concurrentQueue, ^{ 138 [TestAllExtensions parseFromData:allExtensionsData 139 extensionRegistry:[UnittestRoot extensionRegistry] 140 error:NULL]; 141 }); 142 143 dispatch_group_notify(group, concurrentQueue, 144 ^{ 145 }); 146 147 dispatch_release(group); 148 } 149 }]; 150 151 dispatch_release(concurrentQueue); 152} 153 154- (void)testExtensionsPerformance { 155 [self measureBlock:^{ 156 for (int i = 0; i < 200; ++i) { 157 TestAllExtensions* message = [[TestAllExtensions alloc] init]; 158 [self setAllExtensions:message repeatedCount:kRepeatedCount]; 159 NSData* rawBytes = [message data]; 160 [message release]; 161 TestAllExtensions* message2 = [[TestAllExtensions alloc] initWithData:rawBytes error:NULL]; 162 [message2 release]; 163 } 164 }]; 165} 166 167- (void)testPackedTypesPerformance { 168 [self measureBlock:^{ 169 for (int i = 0; i < 1000; ++i) { 170 TestPackedTypes* message = [[TestPackedTypes alloc] init]; 171 [self setPackedFields:message repeatedCount:kRepeatedCount]; 172 NSData* rawBytes = [message data]; 173 [message release]; 174 message = [[TestPackedTypes alloc] initWithData:rawBytes error:NULL]; 175 [message release]; 176 } 177 }]; 178} 179 180- (void)testPackedExtensionsPerformance { 181 [self measureBlock:^{ 182 for (int i = 0; i < 1000; ++i) { 183 TestPackedExtensions* message = [[TestPackedExtensions alloc] init]; 184 [self setPackedExtensions:message repeatedCount:kRepeatedCount]; 185 NSData* rawBytes = [message data]; 186 [message release]; 187 TestPackedExtensions* message2 = [[TestPackedExtensions alloc] initWithData:rawBytes 188 error:NULL]; 189 [message2 release]; 190 } 191 }]; 192} 193 194- (void)testHas { 195 TestAllTypes* message = [self allSetRepeatedCount:1]; 196 [self measureBlock:^{ 197 for (int i = 0; i < 10000; ++i) { 198 [message hasOptionalInt32]; 199 message.hasOptionalInt32 = NO; 200 [message hasOptionalInt32]; 201 202 [message hasOptionalInt64]; 203 message.hasOptionalInt64 = NO; 204 [message hasOptionalInt64]; 205 206 [message hasOptionalUint32]; 207 message.hasOptionalUint32 = NO; 208 [message hasOptionalUint32]; 209 210 [message hasOptionalUint64]; 211 message.hasOptionalUint64 = NO; 212 [message hasOptionalUint64]; 213 214 [message hasOptionalSint32]; 215 message.hasOptionalSint32 = NO; 216 [message hasOptionalSint32]; 217 218 [message hasOptionalSint64]; 219 message.hasOptionalSint64 = NO; 220 [message hasOptionalSint64]; 221 222 [message hasOptionalFixed32]; 223 message.hasOptionalFixed32 = NO; 224 [message hasOptionalFixed32]; 225 226 [message hasOptionalFixed64]; 227 message.hasOptionalFixed64 = NO; 228 [message hasOptionalFixed64]; 229 230 [message hasOptionalSfixed32]; 231 message.hasOptionalSfixed32 = NO; 232 [message hasOptionalSfixed32]; 233 234 [message hasOptionalSfixed64]; 235 message.hasOptionalSfixed64 = NO; 236 [message hasOptionalSfixed64]; 237 238 [message hasOptionalFloat]; 239 message.hasOptionalFloat = NO; 240 [message hasOptionalFloat]; 241 242 [message hasOptionalDouble]; 243 message.hasOptionalDouble = NO; 244 [message hasOptionalDouble]; 245 246 [message hasOptionalBool]; 247 message.hasOptionalBool = NO; 248 [message hasOptionalBool]; 249 250 [message hasOptionalString]; 251 message.hasOptionalString = NO; 252 [message hasOptionalString]; 253 254 [message hasOptionalBytes]; 255 message.hasOptionalBytes = NO; 256 [message hasOptionalBytes]; 257 258 [message hasOptionalGroup]; 259 message.hasOptionalGroup = NO; 260 [message hasOptionalGroup]; 261 262 [message hasOptionalNestedMessage]; 263 message.hasOptionalNestedMessage = NO; 264 [message hasOptionalNestedMessage]; 265 266 [message hasOptionalForeignMessage]; 267 message.hasOptionalForeignMessage = NO; 268 [message hasOptionalForeignMessage]; 269 270 [message hasOptionalImportMessage]; 271 message.hasOptionalImportMessage = NO; 272 [message hasOptionalImportMessage]; 273 274 [message.optionalGroup hasA]; 275 message.optionalGroup.hasA = NO; 276 [message.optionalGroup hasA]; 277 278 [message.optionalNestedMessage hasBb]; 279 message.optionalNestedMessage.hasBb = NO; 280 [message.optionalNestedMessage hasBb]; 281 282 [message.optionalForeignMessage hasC]; 283 message.optionalForeignMessage.hasC = NO; 284 [message.optionalForeignMessage hasC]; 285 286 [message.optionalImportMessage hasD]; 287 message.optionalImportMessage.hasD = NO; 288 [message.optionalImportMessage hasD]; 289 290 [message hasOptionalNestedEnum]; 291 message.hasOptionalNestedEnum = NO; 292 [message hasOptionalNestedEnum]; 293 294 [message hasOptionalForeignEnum]; 295 message.hasOptionalForeignEnum = NO; 296 [message hasOptionalForeignEnum]; 297 298 [message hasOptionalImportEnum]; 299 message.hasOptionalImportEnum = NO; 300 [message hasOptionalImportEnum]; 301 302 [message hasOptionalStringPiece]; 303 message.hasOptionalStringPiece = NO; 304 [message hasOptionalStringPiece]; 305 306 [message hasOptionalCord]; 307 message.hasOptionalCord = NO; 308 [message hasOptionalCord]; 309 310 [message hasDefaultInt32]; 311 message.hasDefaultInt32 = NO; 312 [message hasDefaultInt32]; 313 314 [message hasDefaultInt64]; 315 message.hasDefaultInt64 = NO; 316 [message hasDefaultInt64]; 317 318 [message hasDefaultUint32]; 319 message.hasDefaultUint32 = NO; 320 [message hasDefaultUint32]; 321 322 [message hasDefaultUint64]; 323 message.hasDefaultUint64 = NO; 324 [message hasDefaultUint64]; 325 326 [message hasDefaultSint32]; 327 message.hasDefaultSint32 = NO; 328 [message hasDefaultSint32]; 329 330 [message hasDefaultSint64]; 331 message.hasDefaultSint64 = NO; 332 [message hasDefaultSint64]; 333 334 [message hasDefaultFixed32]; 335 message.hasDefaultFixed32 = NO; 336 [message hasDefaultFixed32]; 337 338 [message hasDefaultFixed64]; 339 message.hasDefaultFixed64 = NO; 340 [message hasDefaultFixed64]; 341 342 [message hasDefaultSfixed32]; 343 message.hasDefaultSfixed32 = NO; 344 [message hasDefaultSfixed32]; 345 346 [message hasDefaultSfixed64]; 347 message.hasDefaultSfixed64 = NO; 348 [message hasDefaultSfixed64]; 349 350 [message hasDefaultFloat]; 351 message.hasDefaultFloat = NO; 352 [message hasDefaultFloat]; 353 354 [message hasDefaultDouble]; 355 message.hasDefaultDouble = NO; 356 [message hasDefaultDouble]; 357 358 [message hasDefaultBool]; 359 message.hasDefaultBool = NO; 360 [message hasDefaultBool]; 361 362 [message hasDefaultString]; 363 message.hasDefaultString = NO; 364 [message hasDefaultString]; 365 366 [message hasDefaultBytes]; 367 message.hasDefaultBytes = NO; 368 [message hasDefaultBytes]; 369 370 [message hasDefaultNestedEnum]; 371 message.hasDefaultNestedEnum = NO; 372 [message hasDefaultNestedEnum]; 373 374 [message hasDefaultForeignEnum]; 375 message.hasDefaultForeignEnum = NO; 376 [message hasDefaultForeignEnum]; 377 378 [message hasDefaultImportEnum]; 379 message.hasDefaultImportEnum = NO; 380 [message hasDefaultImportEnum]; 381 382 [message hasDefaultStringPiece]; 383 message.hasDefaultStringPiece = NO; 384 [message hasDefaultStringPiece]; 385 386 [message hasDefaultCord]; 387 message.hasDefaultCord = NO; 388 [message hasDefaultCord]; 389 } 390 }]; 391} 392 393@end 394