zoukankan      html  css  js  c++  java
  • iOS 性能小点

      这篇文章只是对一些测试结果进行展现,但可以根据这些点,开发的时候尽量避免不必要的性能问题。


      本文中主要做了两项测试,对成员变量的设置及拼接字用不同方式下的耗时。虽然测试代码很简单,但还是贴一下

    //
    //  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传送门

    (未完待续,还没其它点子,欢迎补充...)

    作者:xianmingchen
    出处:http://www.cnblogs.com/chenxianming/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任权利。
  • 相关阅读:
    正交矩阵(部分转载)
    向量的点乘和叉乘
    随机森林
    PCA和LDA
    SIFT和SURF特征(草稿)
    12-赵志勇机器学习-Label_Propagation
    11-赵志勇机器学习-DBSCAN聚类
    09-赵志勇机器学习-k-means
    10-赵志勇机器学习-meanshift
    09-numpy-笔记-repeat
  • 原文地址:https://www.cnblogs.com/chenxianming/p/5670646.html
Copyright © 2011-2022 走看看