看了sunyxxx的博客,学习的同时,顺便测试一下。
sunyxxx的测试代码
CFAbsoluteTime startNSLog = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < 10000; i++) {
NSLog(@"%d", i);
}
CFAbsoluteTime endNSLog = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime startPrintf = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < 10000; i++) {
printf("%d\n", i);
}
CFAbsoluteTime endPrintf = CFAbsoluteTimeGetCurrent();
NSLog(@"NSLog time: %lf, printf time: %lf", endNSLog - startNSLog, endPrintf - startPrintf);
这个时间和机器肯定有关系,只看它们的差别就好。为了全面性,尝试了三种平台:
NSLog time: 4.985445, printf time: 0.084193 // mac
NSLog time: 5.562460, printf time: 0.019408 // 模拟器
NSLog time: 10.471490, printf time: 0.090503 // 真机调试(iphone5)
可以发现,在mac上(模拟器其实也算是mac吧)速度差别达到了60倍左右,而真机调试甚至达到了离谱的100多倍。
这个是2014年的测试结果。
时至今日,看下是否还适合。 看测试结果:(都是debug环境)
NSLog time: 0.057262, printf time: 0.009890 //mac
NSLog time: 4.561284, printf time: 0.041259 //模拟器
NSLog time: 0.049688, printf time: 0.010782 //iPad mini5
耗时对比:Mac上NSLog 是printf的5.82倍,模拟器上是114倍,ipadmini5上是4.52倍
测试设备 | NSLog万次耗时 | printf万次耗时 | 倍率 |
---|---|---|---|
18年15'macpro | 0.057262 | 0.009890 | 5.82 |
iphonex模拟器 | 4.561284 | 0.041259 | 114 |
ipadmini5 | 0.049688 | 0.010782 | 4.52 |
结论:针对14年大神们提出的问题,苹果明显对手机、平板、mac等在卖产品的NSLog做了优化,而对模拟器则还是置之不理。甚至比之前更慢了。
原因
- iOS 10之前,NSLog的作用是输出信息到标准的Error控制台和 苹果的日志系统(ASL,Apple System Log)里面。
- iOS10之后,苹果使用新的统一日志系统(Unified Logging System)来记录日志,全面取代ASL的方式,此种方式,是把日志集中存放在内存和数据库里,并提供单一、高效和高性能的接口去获取系统所有级别的消息传递。
- 新的统一日志系统没有ASL那样的接口可以让我们取出全部日志。
解决方法
- iOS 10以前可以通过ASL接口来获取 (开源:CocoaLumberjack)
- iOS10 以后,通过fishhook库hook NSLog方法重定向NSLog函数
- iOS10 以后,使用dup2函数和STDERR句柄重定向NSLog函数
引用
http://blog.sunnyxx.com/2014/04/22/objc_dig_nslog/
https://juejin.im/post/5cb96aa95188253236619a4d
网友评论