这篇文章只是对一些测试结果进行展现,但可以根据这些点,开发的时候尽量避免不必要的性能问题。
本文中主要做了两项测试,对成员变量的设置及拼接字用不同方式下的耗时。虽然测试代码很简单,但还是贴一下
// // XMCPerformanceDemoTests.m // XMCPerformanceDemoTests // // Created by xianmingchen on 16/7/12. // Copyright © 2016年 xianmingchen. All rights reserved. // #import <XCTest/XCTest.h> #import "XMCPerformanceUtil.h" #import <objc/message.h> #import <CoreFoundation/CoreFoundation.h> @interface XMCPerformanceDemoTests : XCTestCase @property (nonatomic, strong) NSString *name; @end @implementation XMCPerformanceDemoTests @synthesize name = _name; - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } #pragma mark - testSetValue #define kName @"name" const NSUInteger kSetValueCount = 100000000; - (void)testSetValueWithProperty { // Put the code you want to measure the time of here. [XMCPerformanceUtil excuteWithCount:kSetValueCount tagName:__func__ block:^{ self.name = nil; self.name = kName; }]; } - (void)testSetValueWithIvar { [XMCPerformanceUtil excuteWithCount:kSetValueCount tagName:__func__ block:^{ _name = nil; _name = kName; }]; } - (void)testSetValueWithKVC { [XMCPerformanceUtil excuteWithCount:kSetValueCount tagName:__func__ block:^{ [self setValue:nil forKey:kName]; [self setValue:kName forKey:kName]; }]; } - (void)testSetValueWithMsgSend { [XMCPerformanceUtil excuteWithCount:kSetValueCount tagName:__func__ block:^{ ((void (*) (id, SEL, id))objc_msgSend)(self, @selector(setName:), nil); ((void (*) (id, SEL, id))objc_msgSend)(self, @selector(setName:), kName); }]; } #pragma mark - testStringCombine #define kCombineStringOne @"CombineStringOne" #define kCombineStringTwo @"kCombineStringTwo" #define kCombiedStringLeng [kCombineStringOne length] + [kCombineStringOne length] const NSUInteger kStringCombineCount = 1000000; - (void)testStringCombineWithFormat { [XMCPerformanceUtil excuteWithCount:kStringCombineCount tagName:__func__ block:^{ NSString *string = [NSString stringWithFormat:@"%@%@", kCombineStringOne, kCombineStringTwo]; }]; } - (void)testStringCombineWithAppend { NSUInteger length = kCombiedStringLeng; [XMCPerformanceUtil excuteWithCount:kStringCombineCount tagName:__func__ block:^{ NSMutableString *string = [NSMutableString stringWithCapacity:kCombiedStringLeng]; [string appendString:kCombineStringOne]; [string appendString:kCombineStringTwo]; }]; } - (void)testStringCombineWithCFMethod { NSUInteger length = kCombiedStringLeng; [XMCPerformanceUtil excuteWithCount:kStringCombineCount tagName:__func__ block:^{ CFMutableStringRef cfString = CFStringCreateMutable(NULL, length); CFStringAppend(cfString, (__bridge CFStringRef)kCombineStringOne); CFStringAppend(cfString, (__bridge CFStringRef)kCombineStringTwo); }]; } - (void)testStringCombineWithSprintf { NSUInteger length = kCombiedStringLeng; [XMCPerformanceUtil excuteWithCount:kStringCombineCount tagName:__func__ block:^{ char *buf = new char[length + 1]; sprintf(buf, "%s%s", kCombineStringOne.UTF8String, kCombineStringTwo.UTF8String); }]; } @end
// // XMCPerformanceUtil.m // XMCPerformanceDemo // // Created by xianmingchen on 16/7/12. // Copyright © 2016年 xianmingchen. All rights reserved. // #import "XMCPerformanceUtil.h" @implementation XMCPerformanceUtil + (void)excuteWithCount:(NSUInteger)count tagName:(const char *)tagName block:(void(^)())excuteBlock { if (!excuteBlock || tagName == NULL) { return; } NSLog(@"%s beginTest", tagName); NSDate *beginDate = [NSDate date]; for (NSInteger i = 0; i < count; i++) { excuteBlock(); } NSDate *endDate = [NSDate date]; NSTimeInterval timeInterval = [endDate timeIntervalSinceDate:beginDate]; NSLog(@"%s endTest", tagName); NSLog(@"%s take %f seconds", tagName, timeInterval); } @end
对于成员变量的设置进行了一亿次,结果如下:
2016-07-14 15:11:45.287 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithIvar] beginTest 2016-07-14 15:11:46.996 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithIvar] endTest 2016-07-14 15:11:46.996 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithIvar] take 1.708654 seconds Test Case '-[XMCPerformanceDemoTests testSetValueWithIvar]' passed (1.710 seconds). Test Case '-[XMCPerformanceDemoTests testSetValueWithKVC]' started. 2016-07-14 15:11:46.997 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithKVC] beginTest 2016-07-14 15:12:00.976 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithKVC] endTest 2016-07-14 15:12:00.976 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithKVC] take 13.978292 seconds Test Case '-[XMCPerformanceDemoTests testSetValueWithKVC]' passed (13.979 seconds). Test Case '-[XMCPerformanceDemoTests testSetValueWithMsgSend]' started. 2016-07-14 15:12:00.977 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithMsgSend] beginTest 2016-07-14 15:12:03.537 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithMsgSend] endTest 2016-07-14 15:12:03.537 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithMsgSend] take 2.559113 seconds Test Case '-[XMCPerformanceDemoTests testSetValueWithMsgSend]' passed (2.560 seconds). Test Case '-[XMCPerformanceDemoTests testSetValueWithProperty]' started. 2016-07-14 15:12:03.538 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithProperty] beginTest 2016-07-14 15:12:06.131 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithProperty] endTest 2016-07-14 15:12:06.132 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testSetValueWithProperty] take 2.593149 seconds Test Case '-[XMCPerformanceDemoTests testSetValueWithProperty]' passed (2.594 seconds).
可以看到按大小排列 KVC(testSetValueWithKVC) > 使用.方法调用(testSetValueWithProperty)>使用objc_msgSend(testSetValueWithMsgSend)> 直接用成员变量(testSetValueWithIvar)。具体原理可自行了解,也不难。看回结果,比较值得关注的是通过KVC的性能实现是太低了,非必要不建议使用,面使用成员变量比使用.方法还是高一点点,推荐。
对于字符串的拼接是不同方式进行了一百万次操作,结果如下:
2016-07-14 15:12:06.133 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithAppend] beginTest 2016-07-14 15:12:06.798 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithAppend] endTest 2016-07-14 15:12:06.798 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithAppend] take 0.664613 seconds Test Case '-[XMCPerformanceDemoTests testStringCombineWithAppend]' passed (0.666 seconds). Test Case '-[XMCPerformanceDemoTests testStringCombineWithCFMethod]' started. 2016-07-14 15:12:06.799 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithCFMethod] beginTest 2016-07-14 15:12:07.271 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithCFMethod] endTest 2016-07-14 15:12:07.272 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithCFMethod] take 0.472003 seconds Test Case '-[XMCPerformanceDemoTests testStringCombineWithCFMethod]' passed (0.473 seconds). Test Case '-[XMCPerformanceDemoTests testStringCombineWithFormat]' started. 2016-07-14 15:12:07.273 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithFormat] beginTest 2016-07-14 15:12:08.499 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithFormat] endTest 2016-07-14 15:12:08.499 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithFormat] take 1.225532 seconds Test Case '-[XMCPerformanceDemoTests testStringCombineWithFormat]' passed (1.416 seconds). Test Case '-[XMCPerformanceDemoTests testStringCombineWithSprintf]' started. 2016-07-14 15:12:08.689 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithSprintf] beginTest 2016-07-14 15:12:09.012 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithSprintf] endTest 2016-07-14 15:12:09.012 XMCPerformanceDemo[31074:2951062] -[XMCPerformanceDemoTests testStringCombineWithSprintf] take 0.322741 seconds
可以看到 stringWithFormat > Append > CFAppend > Sprinf。系统的stringWithFormat其实效率其实是很低的。做这个测试原由是我们发现写日志代码中stringWithFormat耗时很大,后面改成了Sprinf拼接,性能提升一半以上。并不是说这样我们就不用stringWithFormat。但有些情况最好不用,如:调用次数好多的地方(如日志),性能要求高(tableViewCellForRow中)等。测试代码Demo传送门。
(未完待续,还没其它点子,欢迎补充...)