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的实践
相关文章:
OSLog与NSLog对比
NSLog: NSLog的文档,第一句话就说:Logs an error message to the Apple System Log facility.,所以首先,NSLog就不是设计作为普通的debug log的,而是error log;其次,NSLog也并非是printf的简单…...
全网最细,Fiddler修改接口返回数据详细步骤实战,辅助接口测试...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 在测试的过程中&a…...
Mysql自动同步的详细设置步骤
以下步骤是真实的测试过程,将其记录下来,与大家共同学习。 一、环境说明: 1、主数据库: (1)操作系统:安装在虚拟机中的CentOS Linux release 7.4.1708 (Core) [rootlocalhost ~]# cat /etc/redh…...
opencv-38 形态学操作-闭运算(先膨胀,后腐蚀)cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
闭运算是先膨胀、后腐蚀的运算,它有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景图像进行连接。 例如,在图 8-17 中,通过先膨胀后腐蚀的闭运算去除了原始图像内部的小孔(内部闭合的…...
jenkins gitlab多分支构建发布
内容背景介绍 这个是新手教程,普及概念为主 公司现在还使用单分支发布测试环境和生产,多人协同开发同一个项目导致测试环境占用等待等情况 测试环境占用等待问题 测试环境代码直接合并到 master,容易导致误发布到生产的情况 避免多版本同时发布测试不完善的情况出现 中间件…...
刷题笔记 day8
1004 最大连续1的个数 III 这道题要求将原数组中的0翻转成1,求出最大元素全是1的子数组长度,看这道题第一感觉还要将里面的0变成1,感觉这道题解决起来很麻烦,但是我们可以转变思路,找出其最大子数组,使得子…...
C 语言的表达式
表达式 expression 表达式由运算符和运算对象组成。 最简单的表达式是一个单独的运算对象,以此为基础可以建立复杂的表达式。 一些表达式由子表达式(subexpression)组成。子表达式即较小的表达式。 这些都是一些表达式: -4 a…...
C++设计模式创建型之单例模式
一、概述 单例模式也称单态模式,是一种创建型模式,用于创建只能产生一个对象实例的类。例如,项目中只存在一个声音管理系统、一个配置系统、一个文件管理系统、一个日志系统等,甚至如果吧整个Windows操作系统看成一个项目…...
杂记 | 记录一次使用Docker安装gitlab-ce的过程(含配置交换内存)
文章目录 01 准备工作02 (可选)配置交换内存03 编辑docker-compose.yml04 启动并修改配置05 nginx反向代理06 (可选)修改配置文件07 访问并登录 01 准备工作 最近想自建一个gitlab服务来保存自己的项目,于是找到gitla…...
MyBatis@Param注解的用法
一、前言 本人在学习mybatis的过程中遇到的一个让人不爽的bug,在查找了些相关的资料后得以解决,遂记录。 二、报错及解决 mapper中有一方法: Select("select * from emp " "where name like concat(%, #{name}, %) "…...
Shader 编程:GLSL 重要的内置函数
该原创文章首发于微信公众号:字节流动 未经作者(微信ID:Byte-Flow)允许,禁止转载 前面发了一些关于 Shader 编程的文章,有读者反馈太碎片化了,希望这里能整理出来一个系列,方便系统的…...
浏览器同源策略
浏览器同源策略 同源策略:是一个重要的浏览器的安全策略,用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互 它能帮助阻隔恶意文档,减少可能被攻击的媒介 例如:被钓鱼网站收集信息,使用ajax发起…...
GD32F103的EXTI中断和EXTI事件
GD32F103的EXTI可以产生中断,也产生事件信号。 GD32F03的EXTI触发源: 1、I/O管脚的16根线; 2、内部模块的4根线(包括LVD、RTC闹钟、USB唤醒、以太网唤醒)。 通过配置GPIO模块的AFIO_EXTISSx寄存器,所有的GPIO管脚都可以被选作EXTI的触发源…...
了解 spring MVC + 使用spring MVC - springboot
前言 本篇介绍什么是spring MVC ,如何使用spring MVC,了解如何连接客户端与后端,如何从前端获取各种参数;如有错误,请在评论区指正,让我们一起交流,共同进步! 文章目录 前言1. 什么…...
C#中的Invoke
在 C# 中,Invoke() 是一个用于调用方法的方法,它能够在运行时动态地调用一个方法。 Invoke() 方法的使用方式有两种: 通过 MethodInfo 对象调用: using System.Reflection;namespace ConsoleApp_Invoke {public class Program{…...
Hive终端命令行打印很多日志时,如何设置日志级别
示例:use test; 切换到test数据库时,输出很多日志信息不方便看结果,如下图。 解决方法: 退出hive命令行界面(ctrlC)执行“vi /usr/local/apache-hive-3.1.2-bin/conf/log4j.properties”命令,创…...
Android的PopupWindow(详细版)
经典好文推荐,通过阅读本文,您将收获以下知识点: 一、PopupWindow简介 二、PopupWindow 的使用方法 三、底部PopupWindow的实现 四、参考文献 一、PopupWindow简介 在学习PopupWindow之前,我们先了解一下PopupWindow的继承关系。 PopupWindow继承关系如下: java.lang.Obje…...
Navicat远程连接Linux的MySQL
打开Linux终端,进入root权限,用vim打开MySQL的配置文件 vim /etc/mysql/mysql.conf.d/mysqld.cnf将bind-address的值改为0.0.0.0 进入MySQL mysql -u root -p 将root用户改为允许远程登录 update user set host % where user root; 创建用户 CRE…...
Spring IOC
◆ 传统Javaweb开发的困惑 ◆ IoC、DI和AOP思想提出 ◆ Spring框架的诞生 Spring | Home IOC控制反转:BeanFactory 快速入门 package com.xiaolin.service.Impl;import com.xiaolin.dao.UserDao; import com.xiaolin.service.UserService;public class UserServic…...
华为OD机试真题【上班之路】
1、题目描述 【上班之路】 Jungle 生活在美丽的蓝鲸城,大马路都是方方正正,但是每天马路的封闭情况都不一样。 地图由以下元素组成: 1)”.” — 空地,可以达到; 2)”*” — 路障,不可达到; 3&a…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
