iOS之NSDateFormatter 性能瓶颈

本文介绍NSDateFormatter的性能瓶颈,以及如何解决性能问题。

分别用NSDateFormatter和 C 的localtime()方法将时间转化成一个可读的字符串,转化1024 * 10次,然后对比一下消耗的时间

static NSUInteger totalTimes = 1024 * 10;

@interface ViewController ()
@property (nonatomic, strong) NSString *dateAsString;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self converDateToStringUsingDateFormatter];
    
    [self convertDateToStrUsingCLocaltime];
}

- (void)converDateToStringUsingDateFormatter {
    CFAbsoluteTime then = CFAbsoluteTimeGetCurrent();
    for (NSUInteger i = 0; i < totalTimes; i++) {
        NSDateFormatter *newDateForMatter = [[NSDateFormatter alloc] init];
        [newDateForMatter setDateFormat:@"yyyy-MM-dd"];
        self.dateAsString = [newDateForMatter stringFromDate:[NSDate date]];
    }
    CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
    NSLog(@"Convert date to string using NSDateFormatte cost time:%f seconds \n",now - then);
}

- (void)convertDateToStrUsingCLocaltime {
    CFAbsoluteTime then = CFAbsoluteTimeGetCurrent();
    for (NSUInteger i = 0; i < totalTimes; i++) {
        time_t timeInterval = [NSDate date].timeIntervalSince1970;
        struct tm *cTime = localtime(&timeInterval);
        self.dateAsString = [NSString stringWithFormat:@"%d-%02d-%02d", cTime->tm_year + 1900, cTime->tm_mon + 1, cTime->tm_mday];
    }
    CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
    NSLog(@"Convert date to string using localtime cost time:%f seconds \n",now - then);
}

运行结果如下:

image.png

通过运行结果我们可以得知,使用NSDateFormatter耗时1.5S,使用localtime耗时0.6S,也就是说NSDateFormatter要比localtime 慢3倍+以上。

使用instruments 跑一下 time profile,对比一下两种方式花费时间对比.

time-profile.png

通过分析可以看到性能差距如此之大

为什么NSDateFormatter这么耗时呢?

苹果官方文档中有提到

“Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static
variable.”

也就是说,创建NSDateFormatter的过程开销很大!建议使用时保持一个单例,而不是每次去重新创建
NSDateFormatter对象。

// 声明一个变量
@property (nonatomic, strong) NSDateFormatter *dateFormatter;

// 懒加载实现
- (NSDateFormatter *)dateFormatter {
    if (!_dateFormatter) {
        _dateFormatter = [[NSDateFormatter alloc] init];
        [_dateFormatter setDateFormat:@"yyyy-MM-dd"];
    }
    return _dateFormatter;
}

// 使用单例转换时间
- (void)converDateToStringUsingSingleDateFormatter {
    CFAbsoluteTime then = CFAbsoluteTimeGetCurrent();
    for (NSUInteger i = 0; i < totalTimes; i++) {
        self.dateAsString = [self.dateFormatter stringFromDate:[NSDate date]];
    }
    CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
    NSLog(@"Convert date to string using Single NSDateFormatte cost time:%f seconds \n",now - then);
}

运行结果对比:

image.png

通过运行结果可以看出,如果使用单例,NSDateFormat 开销和localtime()的开销差不多,甚至会稍快一些。

综上所述,最佳实践是,在工程中添加一个NSDateFormatter的单例对象供全工程使用,需要注意的是,NSDateFormatter在iOS7之后(包括iOS7)才是线程安全的。


本文参考Joey_Xu的NSDateFormatter最佳实践,非常感谢该作者


项目连接地址

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容