docs: message

This commit is contained in:
杭城小刘
2020-06-28 12:44:10 +08:00
parent d2500224fe
commit 27c2d9dc0f
2 changed files with 32 additions and 38 deletions

View File

@@ -27,7 +27,7 @@ _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(p_di
#### 1. 屏幕绘制原理
### 1. 屏幕绘制原理
![老式 CRT 显示器原理](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-02-04-ios_screen_scan.png)
@@ -70,7 +70,7 @@ _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(p_di
#### 2. 卡顿产生的原因
### 2. 卡顿产生的原因
@@ -90,14 +90,14 @@ CPU 和 GPU 资源消耗原因很多,比如对象的频繁创建、属性调
#### 3. APM 如何监控卡顿并上报
### 3. APM 如何监控卡顿并上报
CADisplayLink 肯定不用了,这个 FPS 仅作为参考。一般来讲卡顿的监测有2种方案**监听 RunLoop 状态回调、子线程 ping 主线程**
##### 3.1 RunLoop 状态监听的方式
#### 3.1 RunLoop 状态监听的方式
RunLoop 负责监听输入源进行调度处理。比如网络、输入设备、周期性或者延迟事件、异步回调等。RunLoop 会接收2种类型的输入源一种是来自另一个线程或者来自不同应用的异步消息source0事件、另一种是来自预定或者重复间隔的事件。
@@ -363,7 +363,7 @@ dispatch_async(dispatch_get_global_queue(0, 0), ^{
##### 3.2 子线程 ping 主线程监听的方式
#### 3.2 子线程 ping 主线程监听的方式
开启一个子线程创建一个初始值为0的信号量、一个初始值为 YES 的布尔值类型标志位。将设置标志位为 NO 的任务派发到主线程中去,子线程休眠阈值时间,时间到后判断标志位是否被主线程成功(值为 NO如果没成功则认为猪线程发生了卡顿情况此时 dump 堆栈信息并结合数据上报机制,按照一定策略上传数据到服务器。数据上报会在 [打造功能强大、灵活可配置的数据上报组件](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.80.md) 讲
@@ -394,7 +394,7 @@ while (self.isCancelled == NO) {
#### 4. 堆栈 dump
### 4. 堆栈 dump
方法堆栈的获取是一个麻烦事。理一下思路。`[NSThread callStackSymbols]` 可以获取当前线程的调用栈。但是当监控到卡顿发生,需要拿到主线程的堆栈信息就无能为力了。从任何线程回到主线程这条路走不通。先做个知识回顾。
@@ -414,7 +414,7 @@ while (self.isCancelled == NO) {
#### 5. Mach Task 知识
### 5. Mach Task 知识
**Mach task:**
@@ -501,7 +501,7 @@ static mach_port_t main_thread_id;
#### 1. App 启动时间的监控
### 1. App 启动时间的监控
应用启动时间是影响用户体验的重要因素之一,所以我们需要量化去衡量一个 App 的启动速度到底有多快。启动分为冷启动和热启动。
@@ -531,7 +531,7 @@ double timeSpan = (timelapse * g_cmmStartupMonitorTimebaseInfoData.numer) / (g_c
#### 2. 线上监控启动时间就好,但是在开发阶段需要对启动时间做优化。
### 2. 线上监控启动时间就好,但是在开发阶段需要对启动时间做优化。
要优化启动时间,就先得知道在启动阶段到底做了什么事情,针对现状作出方案。
@@ -549,7 +549,7 @@ Main 阶段
![Main 阶段](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-02-10-AppSpeed-Main.png)
##### 2.1 加载 Dylib
#### 2.1 加载 Dylib
每个动态库的加载dyld 需要
- 分析所依赖的动态库
@@ -566,7 +566,7 @@ Main 阶段
##### 2.2 Rebase && Binding
#### 2.2 Rebase && Binding
优化:
- 减少 Objc 类数量,减少 selector 数量,把未使用的类和函数都可以删掉
@@ -575,14 +575,14 @@ Main 阶段
##### 2.3 Initializers
#### 2.3 Initializers
优化:
- 使用 `+initialize` 代替 `+load`
- 不要使用过 attribute*((constructor)) 将方法显示标记为初始化器,而是让初始化方法调用时才执行。比如使用 dispatch_one、pthread_once() 或 std::once()。也就是第一次使用时才初始化,推迟了一部分工作耗时也尽量不要使用 c++ 的静态对象
##### 2.4 pre-main 阶段影响因素
#### 2.4 pre-main 阶段影响因素
- 动态库加载越多,启动越慢。
- ObjC 类越多,函数越多,启动越慢。
@@ -607,7 +607,7 @@ Main 阶段
图片小了IO操作量就小了启动当然就会快了比较靠谱的压缩算法是 TinyPNG。
##### 2.5 main 阶段优化
#### 2.5 main 阶段优化
- 减少启动初始化的流程。能懒加载就懒加载,能放后台初始化就放后台初始化,能延迟初始化的就延迟初始化,不要卡主线程的启动时间,已经下线的业务代码直接删除
- 优化代码逻辑。去除一些非必要的逻辑和代码,减小每个流程所消耗的时间
@@ -621,7 +621,7 @@ Main 阶段
#### 1. CPU 架构
### 1. CPU 架构
CPUCentral Processing Unit中央处理器市场上主流的架构有 ARMarm64、Intelx86、AMD 等。其中 Intel 使用 CISCComplex Instruction Set ComputerARM 使用 RISCReduced Instruction Set Computer。区别在于**不同的 CPU 设计理念和方法**。
@@ -633,7 +633,7 @@ RISC 架构要求软件来指定各个操作步骤。比如上面的乘法,指
#### 2. 获取线程信息<a name="threadInfo"></a>
### 2. 获取线程信息<a name="threadInfo"></a>
讲完了区别来讲下如何做 CPU 使用率的监控
- 开启定时器,按照设定的周期不断执行下面的逻辑
@@ -717,7 +717,7 @@ for (int i = 0; i < threadCount; i++) {
#### 1. 基础知识准备
### 1. 基础知识准备
硬盘:也叫做磁盘,用于存储数据。你存储的歌曲、图片、视频都是在硬盘里。
@@ -729,7 +729,7 @@ iOS 不支持交换空间?不只是 iOS 不支持交换空间,大多数手
#### 2. iOS 内存知识
### 2. iOS 内存知识
内存RAM与 CPU 一样都是系统中最稀少的资源也很容易发生竞争应用内存与性能直接相关。iOS 没有交换空间作为备选资源,所以内存资源尤为重要。
@@ -804,9 +804,9 @@ App 运行内存 = pageNumbers * pageSize。因为 Compressed Memory 属于 Dirt
#### 3. 获取内存信息
### 3. 获取内存信息
##### 3.1 通过 JetsamEvent 日志计算内存限制值
#### 3.1 通过 JetsamEvent 日志计算内存限制值
当 App 被 Jetsam 机制杀死时手机会生成系统日志。查看路径Settings-Privacy-Analytics & Improvements- Analytics Data设置-隐私- 分析与改进-分析数据),可以看到 `JetsamEvent-2020-03-14-161828.ips` 形式的日志,以 JetsamEvent 开头。这些 JetsamEvent 日志都是 iOS 系统内核强杀掉那些优先级不高idle、frontmost、suspended且占用内存超过系统内存限制的 App 留下的。
@@ -1379,7 +1379,7 @@ memorystatus_jld_eval_period_msecs = 6000; /* 6000 msecs == 6 second window */
##### 3.2 开发者们整理所得
#### 3.2 开发者们整理所得
[stackoverflow](https://stackoverflow.com/questions/5887248/ios-app-maximum-memory-budget/15200855#15200855) 上有一份数据,整理了各种设备的 OOM 临界值
@@ -1420,7 +1420,7 @@ memorystatus_jld_eval_period_msecs = 6000; /* 6000 msecs == 6 second window */
##### 3.3 触发当前 App 的 high water mark
#### 3.3 触发当前 App 的 high water mark
我们可以写定时器,不断的申请内存,之后再通过 `phys_footprint` 打印当前占用内存,按道理来说不断申请内存即可触发 Jetsam 机制,强杀 App那么**最后一次打印的内存占用也就是当前设备的内存上限值**。
@@ -1453,7 +1453,7 @@ timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selec
##### 3.4 适用于 iOS13 系统的获取方式
#### 3.4 适用于 iOS13 系统的获取方式
iOS13 开始 <os/proc.h> 中 `size_t os_proc_available_memory(void); ` 可以查看当前可用内存。
@@ -1533,7 +1533,7 @@ CGFloat memoryUsed = (CGFloat)(vmInfo.phys_footprint/1024.0/1024.0);
##### 3.5 通过 XNU 获取内存限制值
#### 3.5 通过 XNU 获取内存限制值
在 XNU 中,有专门用于获取内存上限值的函数和宏,可以通过 `memorystatus_priority_entry` 这个结构体得到所有进程的优先级和内存限制值。
@@ -1602,7 +1602,7 @@ for 循环打印出每个进程(也就是 App的 pid、Priority、User Data
#### 4. 如何判定发生了 OOM
### 4. 如何判定发生了 OOM
OOM 导致 crash 前app 一定会收到低内存警告吗?
@@ -1655,7 +1655,7 @@ for (NSInteger index = 0; index < 10000000; index++) {
#### 5. 内存信息收集
### 5. 内存信息收集
要想精确的定位问题,就需要 dump 所有对象及其内存信息。当内存接近系统内存上限的时候,收集并记录所需信息,结合一定的数据上报机制,上传到服务器,分析并修复。
@@ -1845,7 +1845,7 @@ ASLR: `slide` 函数虚拟地址加载到进程内存的随机偏移量,每
#### 6. 开发阶段针对内存我们能做些什么
### 6. 开发阶段针对内存我们能做些什么
1. 图片缩放
@@ -1934,7 +1934,7 @@ ASLR: `slide` 函数虚拟地址加载到进程内存的随机偏移量,每
###1. App 网络请求过程
### 1. App 网络请求过程
![网络请求各阶段](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-04-03-NetworkTime.png)
@@ -2998,11 +2998,7 @@ CFNetwork 使用 CFReadStreamRef 来传递数据,使用回调函数的形式
```
![method swizzling](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-04-09-methodSwizzling.png)
![isa swizzling](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-04-13-isaSwizzling.png)
![isa swizzling](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-04-13-isaSwizzling.png)
@@ -3207,7 +3203,7 @@ HTTP 请求报文结构
下图是在终端使用 `curl` 查看一个完整的请求和响应数据
![qing](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-05-14-HTTPRequestStructure.png)
![curl查看HTTP响应](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-05-14-HTTPRequestStructure.png)
我们都知道在 HTTP 通信中,响应数据会使用 gzip 或其他压缩方式压缩,用 NSURLProtocol 等方案监听,用 NSData 类型去计算分析流量等会造成数据的不精确,因为正常一个 HTTP 响应体的内容是使用 gzip 或其他压缩方式压缩的,所以使用 NSData 会偏大。
@@ -3831,7 +3827,7 @@ KSCrash 功能齐全,可以捕获如下类型的 Crash
流程图如下:
![KSCrasg流程图](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-05-20-KSCrashStructure.png)
![KSCrash流程图](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-05-20-KSCrashStructure.png)
@@ -6500,7 +6496,7 @@ Crash log 统一入库 Kibana 时是没有符号化的,所以需要符号化
3. 监控的各个能力需要做成可配置,灵活开启关闭。
4. 监控数据需要做内存到文件的写入处理,需要注意策略。监控数据需要存储数据库,数据库大小、设计规则等。存入数据库后如何上报,上报机制等会在另一篇文章讲:[打造一个通用、可配置的数据上报 SDK](./1.80.m)
4. 监控数据需要做内存到文件的写入处理,需要注意策略。监控数据需要存储数据库,数据库大小、设计规则等。存入数据库后如何上报,上报机制等会在另一篇文章讲:[打造一个通用、可配置的数据上报 SDK](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.80.md)
5. 尽量在技术评审后,将各端的技术实现写进文档中,同步给相关人员。比如 ANR 的实现

View File

@@ -2,6 +2,4 @@
1. https://mp.weixin.qq.com/s?__biz=MzI4MTY5NTk4Ng==&mid=2247489516&amp;idx=1&amp;sn=97c8b0fd84e5fc5b214539c135919884&source=41#wechat_redirect
2.