[性能优化]DateFormatter深度优化探索

栏目: C · 发布时间: 5年前

内容简介:在iOS开发中,对日期进行格式化处理通常有三个步骤:在上篇文章函数对日期格式化进行处理,所以本文将对以下几种情况的方法耗时进行评测:

前言

在iOS开发中,对日期进行格式化处理通常有三个步骤:

  • 创建DateFormatter对象

  • 设置日期格式

  • 使用DateFormatter对象对日期进行处理

在上篇文章 《DateFormatter性能优化》 中,我们通过创建单例对象的方式对创建DateFormatter对象,设置日期格式两个步骤进行了缓存,将方法耗时降低为不缓存的方案的10%左右,但是这种优化方法受制于DateFormatter的几个系统方法的执行效率,本身具有一定的局限性。之前在一些文章中,也看到了使用 C语言

size_t     strftime_l(char * __restrict, size_t, const char * __restrict,
        const struct tm * __restrict, locale_t)
        __DARWIN_ALIAS(strftime_l) __strftimelike(3);

函数对日期格式化进行处理,所以本文将对以下几种情况的方法耗时进行评测:

  • 使用Objective-C,不缓存DateFormatter对象

  • 使用Objective-C,缓存DateFormatter对象

  • 使用Objective-C,调用strftime_l做日期处理

  • 使用Swift,不缓存DateFormatter对象

  • 使用Swift,缓存DateFormatter对象

  • 使用Swift,调用strftime_l做日期处理

Objective-C的三种情况下的代码

//不缓存DateFormatter对象
-(void)testDateFormatterInOCWithoutCache:(NSInteger)times {
NSString *string = @"";
NSDate *date;
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
for (int i=0; i
NSDateFormatter *dateFormatter = [[ NSDateFormatter alloc] init];
[dateFormatter setDateFormat: @"yyyy年MM月dd日HH时mm分ss秒"];
date = [ NSDate dateWithTimeIntervalSince1970:( 1545308405 + i)];
string = [dateFormatter stringFromDate:date];
}
CFAbsoluteTime duration = ( CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
NSLog( @"\n不缓存DateFormatter对象的方案:\n计算%ld次\n耗时%f ms\n", ( long)times, duration);
}

//缓存DateFormatter对象
-( void)testDateFormatterInOCWithCache:( NSInteger)times {
NSString *string = @"";
NSDate *date;
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
for ( int i= 0; i
date = [ NSDate dateWithTimeIntervalSince1970:( 1545308405 + i)];
string = [[DateFormatterCache shareInstance].formatterOne stringFromDate:date];
}
CFAbsoluteTime duration = ( CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
NSLog( @"\n缓存DateFormatter对象的方案:\n计算%ld次\n耗时%f ms\n", ( long)times, duration);
}

//使用C语言来做日期处理
-( void)testDateFormatterInC:( NSInteger)times {
NSString *string = @"";
NSDate *date;
time_t timeInterval;
char buffer[ 80];
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
for ( int i= 0; i
date = [ NSDate dateWithTimeIntervalSince1970:( 1545308405 + i)];
timeInterval = [date timeIntervalSince1970];
strftime(buffer, sizeof(buffer), "%Y年%m月%d日%H时%M分%S秒", localtime(&timeInterval));
string = [ NSString stringWithCString:buffer encoding: NSUTF8StringEncoding];
}
CFAbsoluteTime duration = ( CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
NSLog( @"==%@", string);
NSLog( @"\n使用C语言的方案:\n计算%ld次\n耗时%f ms\n", ( long)times, duration);
}

附上tm结构体:

struct tm {
    int tm_sec;     /* seconds after the minute [0-60] */
    int tm_min;     /* minutes after the hour [0-59] */
    int tm_hour;    /* hours since midnight [0-23] */
    int tm_mday;    /* day of the month [1-31] */
    int tm_mon;     /* months since January [0-11] */
    int tm_year;    /* years since 1900 */
    int tm_wday;    /* days since Sunday [0-6] */
    int tm_yday;    /* days since January 1 [0-365] */
    int tm_isdst;   /* Daylight Savings Time flag */
    long    tm_gmtoff;  /* offset from UTC in seconds */
    char    *tm_zone;   /* timezone abbreviation */
};

Swift三种情况下的代码

    //不进行缓存
func testInOldWay(_ times: Int) {
var string = ""
var date = Date.init()
let startTime = CFAbsoluteTimeGetCurrent();
for i in 0..
let formatter = DateFormatter()
formatter.dateFormat = "yyyy年MM月dd日HH时mm分ss秒"
date = Date.init(timeIntervalSince1970: TimeInterval( 1545308405 + i))
string = formatter. string( from: date)
}
let duration = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
print( "使用oldWay计算\n\(times)次,总耗时\n\(duration) ms\n")
}
//进行缓存
func testInNewWay(_ times: Int) {
var string = ""
var date = Date.init()
let startTime = CFAbsoluteTimeGetCurrent();
for i in 0..
date = Date.init(timeIntervalSince1970: TimeInterval( 1545308405 + i))
string = DateFormatterCache.shared.dateFormatterOne. string( from: date)
}
let duration = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
print( "使用缓存Formatter的方案计算\n\(times)次,总耗时\n\(duration) ms\n")
}

//使用C语言来做日期处理
func testFormatterInC(_ times: Int) {
var date = Date.init()
var dateString = ""
var buffer = [Int8](repeating: 0, count: 100)
var time = time_t(date.timeIntervalSince1970)
let format = "%Y年%m月%d日%H时%M分%S秒"
let startTime = CFAbsoluteTimeGetCurrent();
for i in 0..
date = Date.init(timeIntervalSince1970: TimeInterval( 1545308405 + i))
time = time_t(date.timeIntervalSince1970)
strftime(&buffer, buffer.count, format, localtime(&time))
dateString = String.init(cString: buffer, encoding: String.Encoding.utf8) ?? ""
}
let duration = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
print( "使用C语言的方案计算\n\(times)次,总耗时\n\(duration) ms\n")
print(dateString)
}

iOS 12.1 iPhone 7

测试结果:

[性能优化]DateFormatter深度优化探索

测试结果:

在Objective-C中, 不使用缓存,使用缓存,使用C语言函数处理的耗时比约为100:10.7:3.5

在Swift中, 不使用缓存,使用缓存,使用C语言函数处理的耗时比约为100:11.7:6.6

Swift在使用DateFormatter进行处理时,不论是缓存的方案还是不缓存的方案,跟使用Objective-C的耗时基本一致,而在Swift中使用C语言的函数来做日期处理时,时间约为使用Objective-C的两倍,而且当只做一次日期处理时,由于涉及到一些初始资源的初始化,所以看上去比后面执行10次的时间还多

最后

如果项目是Objective-C的项目,我觉得可以采用这种C语言的strftime来做日期处理,能将时间降低为缓存NSDateFormatter的方案的33%左右,如果是Swift项目,调用C语言函数的效率没有在Objective-C项目中那么高,虽然能将时间降低为缓存NSDateFormatter的方案的56%左右,但是在Swift中使用C语言的函数存在一定的风险,在这里风险之一就是 time = time_t(date.timeIntervalSince1970) 这行代码返回的值是time_t类型,time_t类型的定义如下:

public typealias time_t = __darwin_time_t
public typealias __darwin_time_t = Int /* time() */

time_t其实就是Int,当Swift项目运行在32位设备(也就是iphone 5,iphone 5C)上时,Int类型是32位的,最大值为2147483647,如果这是一个时间戳的值,转换为正常时间是2038-01-19 11:14:07,也就是处理的时间是未来的日期,2038年以后的话,会出现数值溢出。

Demo在这里: github.com/577528249/S…

参考资料:

forums.developer.apple.com/thread/2905… stackoverflow.com/questions/2…

作者:Not_Found

链接:https://juejin.im/post/5c1b69dde51d45199c387a73


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

代码整洁之道:程序员的职业素养

代码整洁之道:程序员的职业素养

罗伯特·C.马丁 (Robert C.Martin) / 余晟、章显洲 / 人民邮电出版社 / 2016-9-1 / 49.00元

1. 汇聚编程大师40余年编程生涯的心得体会 2. 阐释软件工艺中的原理、技术、工具和实践 3. 助力专业软件开发人员具备令人敬佩的职业素养 成功的程序员在以往的工作和生活中都曾经历过大大小小的不确定性,承受过永无休止的压力。他们之所以能够成功,是因为拥有一个共同点,都深切关注创建软件所需的各项实践。他们将软件开发视为一种需要精雕细琢加以修炼的技艺,他们以专业人士的标准要求自己,......一起来看看 《代码整洁之道:程序员的职业素养》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器