NSLog的性能问题

看了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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。