OSLog与NSLog对比

NSLog:

NSLog的文档,第一句话就说:Logs an error message to the Apple System Log facility.,所以首先,NSLog就不是设计作为普通的debug log的,而是error log;其次,NSLog也并非是printf的简单封装,而是Apple System Log(ASL)的封装。

ASL是啥?从官方手册上可以看到说明:

These routines provide an interface to the Apple System Log facility. They are intended to be a replacement for the syslog(3) API, which will continue to be supported for backwards compatibility.

这些例程为Apple系统日志功能提供了一个接口。它们旨在取代syslog(3)API,后者将继续支持向后兼容性。

意思就是ASL是个系统级别的log工具,syslog的替代版,提供了一系列强大的log功能。不过一般我们接触不到,NSLog就对它提供了高层次的封装,如这篇文档所提到的:

You can use two interfaces in OS X to log messages: ASL and Syslog. You can also use a number of higher-level approaches such as NSLog. However, because most daemons are not linked against Foundation or the Application Kit, the low-level APIs are often more appropriate。

您可以在OSX中使用两个接口来记录消息:ASL和Syslog。您还可以使用许多更高级的方法,如NSLog。但是,由于大多数守护进程没有与Foundation或应用程序工具包链接,因此底层API通常更合适。

一些底层相关的守护进程(deamons)不会link如Foundation等高层框架,所以asl用在这儿正合适;而asl就是对应应用层的用NSLog。

在CocoaLumberjack的文档中也说了NSLog效率低下的问题:

NSLog does 2 things:

- It writes log messages to the Apple System Logging (asl) facility. This allows log messages to show up in Console.app.

- It also checks to see if the application’s stderr stream is going to a terminal (such as when the application is being run via Xcode). If so it writes the log message to stderr (so that it shows up in the Xcode console).

To send a log message to the ASL facility, you basically open a client connection to the ASL daemon and send the message. BUT - each thread must use a separate client connection. So, to be thread safe, every time NSLog is called it opens a new asl client connection, sends the message, and then closes the connection.

NSLog做两件事:

-它将日志消息写入Apple系统日志(asl)功能。这允许日志消息显示在Console.app中。

-它还检查应用程序的stderr流是否要到达终端(例如当应用程序通过Xcode运行时)。如果是这样,它会将日志消息写入stderr(以便它显示在Xcode控制台中)。

要向ASL设施发送日志消息,基本上需要打开与ASL守护进程的客户端连接并发送消息。但是-每个线程必须使用一个单独的客户端连接。因此,为了线程安全,每次调用NSLog时,它都会打开一个新的asl客户端连接,发送消息,然后关闭连接。

意识大概是说,NSLog会向ASL写log,同时向Terminal写log,而且同时会出现在Console.app中(Mac自带软件,用NSLog打出的log在其中全部可见);不仅如此,每一次NSLog都会新建一个ASL client并向ASL守护进程发起连接,log之后再关闭连接。所以说,当这个过程出现N次时,消耗大量资源导致程序变慢也就不奇怪了。

时间和进程信息

主要原因已经找到,还有个值得注意的问题是NSLog每次会将当前的系统时间,进程和线程信息等作为前缀也打印出来,如:

2023-08-05 16:53:32.177524+0800 刷新冲突[4136:33556] dateToMd5String - d41d8cd98f00b204e9800998ecf8427e

每次格式化生成时间戳也会有一定的性能损耗,当然这些也可能是作为ASL的参数创建的。

OSLog:

苹果官方文档这样介绍:OSLog是一个统一的日志系统,在iOS 10中可用。macOS 10.12及以上版本,tvOS 10.0及以上版本,watchOS 3.0及以上版本。该系统将取代Apple system Logger (ASL)和Syslog api。

它相比以前的NSLog更加优越,苹果极力推荐使用新的日志系统。以前,日志消息被写到磁盘上的特定位置,比如/etc/system.log。统一日志系统将消息存储在内存和数据存储中,而不是写入基于文本的日志文件。

NSLog效率低的原因是NSLog做了两件事:

  • 1.-它将日志消息写入Apple System Logging (asl)设施。这允许日志消息显示在Console.app中。
  • 2.-它还检查应用程序的stderr流是否要去终端(比如当应用程序通过Xcode运行时)。如果是,它将日志消息写入stderr(这样它就会显示在Xcode控制台中)。

要向ASL设施发送日志消息,基本上需要打开到ASL守护进程的客户机连接并发送消息。BUT -每个线程必须使用单独的客户端连接。因此,为了线程安全,每次调用NSLog时,它都会打开一个新的asl客户端连接,发送消息,然后关闭连接。所以说,当这个过程出现N次时,消耗大量资源导致程序变慢也就不奇怪了。

OSLog相比NSlog的优点

1.新的日志系统,跨多个平台Mac,ios,WachOS

2.相比以前的系统更加的高效

3.日志组织的更有条理。有了 Log levels(default info debug error fault)一些第三方的日志如也有类似功能, 日志有分类的功能

4.保护隐私功能,格式化信息

5.日志不是可读文本(用console 及相关命令行工具 log 可以查),但可以打包获取,分发

6.苹果提供了日志处理命令行工具

7.可以使用配置文件对日志进行配置

OSLog重要部分讲解

Log Levels

统一日志系统使用了几个日志级别,它们对应于应用程序可能需要捕获的不同类型的消息,并定义消息何时保存到数据存储中,以及消息保存多长时间。系统为每个级别实现标准行为。可以使用日志命令行工具或自定义配置文件覆盖此行为(请参阅调试时自定义日志行为)。

  • default 默认级别的消息最初存储在内存缓冲区中。在不更改配置的情况下,它们将被压缩并随着内存缓冲区的填充移动到数据存储区。它们会一直保留到超过存储配额,此时,最古老的消息将被清除。使用此级别捕获可能导致失败的信息。
  • info 信息级消息最初存储在内存缓冲区中。如果不进行配置更改,则不会将它们移动到数据存储区,并在内存缓冲区填充时清除它们。但是,当发生错误或错误时,它们会在数据存储中捕获。当信息级别的消息被添加到数据存储中时,它们将一直保留在那里,直到超过存储配额,此时,最古老的消息将被清除。使用此级别捕获对故障排除可能有帮助但不是必需的信息。
  • debug 调试级别的消息只在通过配置更改启用调试日志记录时在内存中捕获。根据配置的持久性设置清除它们。此级别记录的消息包含在开发期间或排除特定问题时可能有用的信息。调试日志记录用于开发环境,而不是发布软件。
  • error 错误级别的消息总是保存在数据存储中。它们会一直保留到超过存储配额,此时,最古老的消息将被清除。错误级消息用于报告流程级错误。如果存在活动对象,则此级别的日志记录将捕获整个流程链的信息。
  • fault 故障级消息总是保存在数据存储中。它们会一直保留到超过存储配额,此时,最古老的消息将被清除。故障级消息仅用于捕获系统级或多进程错误。如果存在活动对象,则此级别的日志记录将捕获整个流程链的信息。

保护隐私功能,格式化信息

要格式化日志消息,请使用标准的NSString或printf格式字符串,如清单4所示。有关格式化规则,请参阅字符串格式说明符。

image.png

// 代码示例
os_log("now build-in %{time_t}d ",Int(Date().timeIntervalSince1970))
os_log("now %@ ", NSDate())
os_log("uuid_t %@ ",NSUUID())
os_log("self %@ ",self)
os_log("string %{public}s ","string")
os_log("iec-bytes %{iec-bytes}d ",1024)// 结果
2022-10-29 15:09:07.724062+0800 SwiftDemo[5317:849193] now build-in 2022-10-29 15:09:07+0800
2022-10-29 15:09:07.724151+0800 SwiftDemo[5317:849193] now Sat Oct 29 15:09:07 2022
2022-10-29 15:09:07.724187+0800 SwiftDemo[5317:849193] uuid_t 7779AA5E-6C78-4D01-8C80-588E0191CDF0
2022-10-29 15:09:07.724216+0800 SwiftDemo[5317:849193] self <SwiftDemo.ViewController: 0x10550ba80>
2022-10-29 15:09:07.724257+0800 SwiftDemo[5317:849193] string string
2022-10-29 15:09:07.724270+0800 SwiftDemo[5317:849193] iec-bytes 1 KiB

三、OSLog的实践

1.基本用法

// 输出一个default-level 信息
os_log("This is a log message.")
// 输出一个info-level 信息
os_log("This is additional info that may be helpful for troubleshooting.", log: OSLog.default, type: .info)
// 输出一个自定义子系统,级别为debug-level 信息
let customLog = OSLog(subsystem: "com.your_company.your_subsystem_name.plist", category: "your_category_name")
os_log("This is info that may be helpful during development or debugging.", log: customLog, type: .debug)
// 示例与结果
let myLog : OSLog = OSLog(subsystem:"mySubsystem", category:"myCategory")
let date = Date()
os_log("测试default-date-%@", date as CVarArg)
os_log(.debug, log: myLog, "测试debug-date-%@", date as CVarArg)
os_log(.error, log: myLog, "测试error-date-%@", date as CVarArg)
os_log(.info, log: myLog, "测试info-date-%@", date as CVarArg)
os_log(.fault, log: myLog, "测试fault-date-%@", date as CVarArg)// 结果:
2022-10-29 14:02:17.336726+0800 SwiftDemo[41978:4599820] 测试default-date-Sat Oct 29 14:02:17 2022
2022-10-29 14:02:17.336798+0800 SwiftDemo[41978:4599820] [myCategory] 测试debug-date-Sat Oct 29 14:02:17 2022
2022-10-29 14:02:17.336850+0800 SwiftDemo[41978:4599820] [myCategory] 测试error-date-Sat Oct 29 14:02:17 2022
2022-10-29 14:02:17.336911+0800 SwiftDemo[41978:4599820] [myCategory] 测试info-date-Sat Oct 29 14:02:17 2022
2022-10-29 14:02:17.337007+0800 SwiftDemo[41978:4599820] [myCategory] 测试fault-date-Sat Oct 29 14:02:17 2022

2.在控制台app中的展示

3.os_log与NSlog效率对比

// 单条线程测试时间对比
private func timeTest() {let startNSLog = CFAbsoluteTimeGetCurrent()for i in 0..<10000 {NSLog("nslog---%d", i)}let endNSLog = CFAbsoluteTimeGetCurrent()let startOSLog = CFAbsoluteTimeGetCurrent()for i in 0..<10000 {os_log("oslog---%d",i)}let endOSLog = CFAbsoluteTimeGetCurrent()print("NSLogTime:%f",endNSLog-startNSLog)print("OSLogTime:%f",endOSLog-startOSLog)
}// 结果
NSLogTime:%f 0.7270380258560181
OSLogTime:%f 0.5310770273208618NSLogTime:%f 0.6149619817733765
OSLogTime:%f 0.4749699831008911NSLogTime:%f 0.7736960649490356
OSLogTime:%f 0.5272040367126465// 多条线程测试时间对比
private func timeTest() {let queue = DispatchQueue(label: "myQueue", attributes: [.concurrent])let startNSLog = CFAbsoluteTimeGetCurrent()for i in 0..<5000 {NSLog("nslog---%d", i)}queue.async {for i in 0..<5000 {queue.sync {NSLog("nslog---%d", i)}}let endNSLog = CFAbsoluteTimeGetCurrent()print("NSLogTime:%f \n",endNSLog-startNSLog)}let startOSLog = CFAbsoluteTimeGetCurrent()for i in 0..<5000 {os_log("oslog---%d",i)}queue.async {for i in 0..<5000 {DispatchQueue.global().sync {os_log("oslog---%d",i)}}let endOSLog = CFAbsoluteTimeGetCurrent()print("OSLogTime:%f",endOSLog-startOSLog)}
}// 结果
NSLogTime:%f 1.227236032485962
OSLogTime:%f 0.8558480739593506NSLogTime:%f 1.2800310850143433
OSLogTime:%f 0.9496610164642334NSLogTime:%f 1.2216260433197021
OSLogTime:%f 0.9060399532318115

实测来看,OSLog 比 NSLog的效率提升了25% - 30%。

OSLog与NSLog,OSLog的实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单元测试用例分组 demo

文章目录 目标1、使用 Category 进行用例分组&#xff08;1&#xff09;设置用例组&#xff08;2&#xff09;编写测试类&#xff0c;case设置对应的用例组&#xff08;3&#xff09;编写执行类&#xff08;4&#xff09;查看运行结果&#xff08;5&#xff09;联系项目 2、参数…

App Cleaner Uninstaller for Mac 苹果电脑软件卸载工具

App Cleaner & Uninstaller 是一款非常有用的 Mac 应用程序清理和卸载工具。它可以彻底地清理系统中的应用程序、扩展和残留文件&#xff0c;以释放磁盘空间并优化系统性能。 此外&#xff0c;它还提供了磁盘空间监控和智能清理建议等功能&#xff0c;使用户可以轻松地管理…

计算机网络性能指标

比特&#xff1a;数据量的单位 KB 2^10B 2^13 bit 比特率&#xff1a;连接在计算机网络上的主机在数字通道上传送比特的速率 kb/s 10^3b/s 带宽&#xff1a;信号所包含的各种频率不同的成分所占据的频率范围 Hz 表示在网络中的通信线路所能传送数据的能力&#xff08…

Meta开源AI音频和音乐生成模型

在过去的几年里&#xff0c;我们看到了AI在图像、视频和文本生成方面的巨大进步。然而&#xff0c;音频生成领域的进展却相对滞后。MetaAI这次再为开源贡献重磅产品&#xff1a;AudioCraft&#xff0c;一个支持多个音频生成模型的音频生成开发框架。 AudioCraft开源地址 开源地…

嵌入式该往哪个方向发展?

1. 你所在的城市嵌入式Linux岗位多吗&#xff1f;我觉得这是影响你做决定的另一个大问题。我们学嵌入式Linux这门技术&#xff0c;绝大部分人是为了从事相关的工作&#xff0c;而不是陶冶情操。但是根据火哥统计来看&#xff0c;嵌入式Linux的普遍薪资虽然高于单片机&#xff0…

C++ Visual Studio工程目录相对路径设置

文章目录 相对路径相对路径是相对vs工程的哪个目录而言书写格式 参考 相对路径 要设对相对路径&#xff0c;需要搞清楚下面两个问题&#xff1a; 相对路径是相对vs工程的哪个目录而言相对路径的书写格式 相对路径是相对vs工程的哪个目录而言 注意&#xff1a; 并非以解决方案…

网络安全进阶学习第十四课——MSSQL注入

文章目录 一、MSsql数据库二、MSsql结构三、MSsql重点表1、master 数据库中的Sysdatabases 表2、Sysobjects 表3、Syscolumns 表 四、Mssql常用函数五、Mssql的报错注入六、Mssql的盲注常用以下函数进行盲注&#xff1a; 七、联合注入1、获取当前表的列数2、获取当前数据库名3、…

网络编程(JavaEE初阶系列10)

目录 前言&#xff1a; 1.网络编程的基础 1.1为什么需要网络编程 1.2什么是网络编程 1.3网络编程中的基本概念 1.3.1发送端和接收端 1.3.2请求和响应 1.3.3客户端和服务端 2.Socket套接字 2.1概念 2.2分类 3.UDP数据报套接字编程 3.1DataGramSocket API 3.2Datagr…

坐标转换-使用geotools读取和转换地理空间表的坐标系(sqlserver、postgresql)

前言&#xff1a; 业务上通过GIS软件将空间数据导入到数据库时&#xff0c;因为不同的数据来源和软件设置&#xff0c;可能导入到数据库的空间表坐标系是各种各样的。 如果要把数据库空间表发布到geoserver并且统一坐标系&#xff0c;只是在geoserver单纯的设置坐标系只是改了…

JMeter命令行执行+生成HTML报告

1、为什么用命令行模式 使用GUI方式启动jmeter&#xff0c;运行线程较多的测试时&#xff0c;会造成内存和CPU的大量消耗&#xff0c;导致客户机卡死&#xff1b; 所以一般采用的方式是在GUI模式下调整测试脚本&#xff0c;再用命令行模式执行&#xff1b; 命令行方式支持在…

MyBatis-动态SQL-foreach

目录 标签有以下常用属性&#xff1a; 小结 <froeach> <foreach>标签有以下常用属性&#xff1a; collection&#xff1a;指定要迭代的集合或数组的参数名&#xff08;遍历的对象&#xff09;。item&#xff1a;指定在迭代过程中的每个元素的别名&#xff08;遍历…

OnlyOffice社区版破解最大连接限制部署

onlyoffice社区版部署并且破解最大连接数 docker镜像 docker pull onlyoffice/documentserver:5.3.1.265.4或更高的版本已经解决了此方法的Bug 运行镜像 docker run -d --name onlyoffice --restartalways -p 暴露端口号:80 onlyoffice/documentserver:5.3.1.26进入容器内部…

策略模式——算法的封装与切换

1、简介 1.1、概述 在软件开发中&#xff0c;常常会遇到这种情况&#xff0c;实现某一个功能有多条途径。每一条途径对应一种算法&#xff0c;此时可以使用一种设计模式来实现灵活地选择解决途径&#xff0c;也能够方便地增加新的解决途径。为了适应算法灵活性而产生的设计模…

[机器学习]线性回归模型

线性回归 线性回归&#xff1a;根据数据&#xff0c;确定两种或两种以上变量间相互依赖的定量关系 函数表达式&#xff1a; y f ( x 1 , x 2 . . . x n ) y f(x_1,x_2...x_n) yf(x1​,x2​...xn​) ​ 回归根据变量数分为一元回归[ y f ( x ) yf(x) yf(x)]和多元回归[ y …

【深度学习Week4】MobileNet_ShuffleNet

报错&#xff1a;unsafe legacy renegotiation disabled 解决方案&#xff1a; 尝试了更换cryptography36.0.2版本&#xff0c;以及更换下载链接的方法&#xff0c;都不行&#xff0c;最后采用了手动下载mat文件并上传到colab的方法 高光谱图像分类数据集简介Indian Pines&…

【果树农药喷洒机器人】Part2:机器人变量喷药系统硬件选型

本专栏介绍&#xff1a;免费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、引言二、变量喷药系统总体要求2.1系统功能要求2.2系统技术要求 三…

4.1 Windows终端安全

数据参考&#xff1a;CISP官方 目录 安全安装保护账户安全本地安全策略安全中心系统服务安全其他安全设置软件安全获取 一、安全安装&#xff08;以安装windows系统为例&#xff09; 选择合适的版本 商业版本&#xff1a;家庭版、专业版、专业工作站版、企业版特殊版本&…

pytest-xdist分布式测试原理浅析

目录 pytest-xdist执行流程&#xff1a; pytest-xdist 模块结构&#xff1a; pytest-xdist分布式测试原理&#xff1a; pytest-xdist源码浅读&#xff1a; pytest-xdist执行流程&#xff1a; 解析命令行参数&#xff1a;pytest-xdist 会解析命令行参数&#xff0c;获取用户…

海外媒体发稿:软文写作方法方式?一篇好的软文理应合理规划?

不同种类的软文会有不同的方式&#xff0c;下面小编就来来给大家分析一下&#xff1a; 方法一、要选定文章的突破点&#xff1a; 所说突破点就是这篇文章文章软文理应以什么样的视角、什么样的见解、什么样的语言设计理念、如何文章文章的标题来写。不同种类的传播效果&#…

【JMeter】 使用Synchronizing Timer设置请求集合点,实现绝对并发

目录 布局设置说明 Number of Simulated Users to Group Timeout in milliseconds 使用时需要注意的点 集合点作用域 实际运行 资料获取方法 布局设置说明 参数说明&#xff1a; Number of Simulated Users to Group 每次释放的线程数量。如果设置为0&#xff0c;等同…