mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
feature: Weex APM
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
## 带你打造一套 APM 监控系统
|
||||
|
||||
> APM 是 Application Performance Monitoring 的缩写,监视和管理软件应用程序的性能和可用性。应用性能管理对一个应用的持续稳定运行至关重要。所以这篇文章就从一个 iOS App 的性能管理的纬度谈谈如何精确监控以及数据如何上报等技术点
|
||||
> APM 是 Application Performance Monitoring 的缩写,监视和管理软件应用程序的性能和可用性。应用性能管理对一个应用的持续稳定运行至关重要。所以这篇文章就从一个 iOS App 的性能管理的维度谈谈如何精确监控以及数据如何上报等技术点
|
||||
|
||||
App 的性能问题是影响用户体验的重要因素之一。性能问题主要包含:Crash、网络请求错误或者超时、UI 响应速度慢、主线程卡顿、CPU 和内存使用率高、耗电量大等等。大多数的问题原因在于开发者错误地使用了线程锁、系统函数、编程规范问题、数据结构等等。解决问题的关键在于尽早的发现和定位问题。
|
||||
App 的性能问题是影响用户体验的重要因素之一。性能问题主要包含:卡顿、Crash、网络请求错误或者超时、UI 响应速度慢、主线程卡顿、CPU 和内存使用率高、耗电量大、Weex/RN/Flutter 页面白屏等等。大多数的问题原因在于开发者错误地使用了线程锁、系统函数、编程规范问题、数据结构等等。解决问题的关键在于尽早的发现和定位问题。
|
||||
|
||||
本篇文章着重总结了 APM 的原因以及如何收集数据。APM 数据收集后结合数据上报机制,按照一定策略上传数据到服务端。服务端消费这些信息并产出报告。请结合[姊妹篇](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.80.md), 总结了如何打造一款灵活可配置、功能强大的数据上报组件。
|
||||
|
||||
@@ -8094,6 +8094,52 @@ runZoned<Future<Null>>(() async {
|
||||
|
||||
|
||||
## 十、子线程 UI 监控
|
||||
### 为什么不能在子线程操作 UI
|
||||
UI 必须在主线程(UI 线程)执行,核心原因是 **UI 框架的单线程模型**设计,为了保证 UI 操作的线程安全、状态一致性和渲染效率,几乎所有的主流 UI 框架(Android、iOS、Web、Windows、Web 前端、Flutter、Weex、RN)都限制:只有主线程才可以访问和修改 UI 控件。
|
||||
|
||||
#### 核心原因:解决“线程安全”与“状态一致性”问题
|
||||
UI 控件(如按钮、文本框)是**共享资源**,且设计时**没有内置线程同步机制(比如锁)**,如果允许多线程直接操作 UI,会引发2个致命问题:
|
||||
|
||||
##### 1. 竞态条件(Race Condition):UI 状态错乱
|
||||
多线程同时修改同一个 UI 控件的属性,会导致 UI 状态“冲突”,比如:
|
||||
- 线程 A 设置 UILabel 的文本为“加载中,正在获取服务端数据...”
|
||||
- 线程 B,设置 UILabel 文字颜色为蓝色
|
||||
- 线程 C,设置 UILabel 为隐藏(此时 UILabel 的文字可能还没更改完,状态不对,但立马被设置为隐藏了)
|
||||
最终出现了 UILabel 的显示错乱,UI 控件卡死,界面闪烁问题
|
||||
|
||||
##### 2. 渲染流程混乱:绘制结果不可预期
|
||||
UI 渲染是个连续的流水线:先计算控件布局(Measure/Layout) -> 绘制控件(Draw) -> 刷新屏幕(Compose)。这个流程需要顺序执行、状态稳定,如果多线程介入:
|
||||
- 线程 A 正在计算布局(比如调整 UILabel 的位置)
|
||||
- 线程 B 突然修改 Frame 大小,导致布局计算结果失效
|
||||
- 最终绘制出界面可能是“按钮位置偏移”、“控件重叠”等异常
|
||||
|
||||
#### 为什么不设计线程安全的 UI 控件?
|
||||
##### 1. 性能暴跌:UI 操作便卡顿
|
||||
UI 操作是非常高频的场景(比如列表在滑动的时候,每秒可能刷新几十次),而加锁会导致性能问题(比如线程 A 给 UILabel 加了锁,线程 B 想要修改文字大小,此时必须等待线程 A 释放锁)。频繁的锁竞争会让 UI 的变化延迟响应,甚至出现“滑动掉帧”问题,或者“点击无响应”-这违背了 UI 对流畅性的核心要求
|
||||
##### 2. 复杂度爆炸:容易引发死锁
|
||||
UI 控件存在依赖关系(比如父子组件、UI 组件树),多线程操作时,可能出现“锁顺序错乱”
|
||||
- 线程 A 锁父控件 -> 再尝试锁子控件
|
||||
- 线程 B 锁子控件 -> 再尝试锁父控件
|
||||
2者相互等待出现死锁
|
||||
|
||||
因此,UI 框架必须满足“牺牲多线程灵活性”,以确保“单线程的简单性、安全性和高效性”,索性一刀切,**所有的 UI 操作必须在主线程上执行**,从根源上避免不符合预期的行为出现
|
||||
|
||||
##### GUI 平台的单线程模型
|
||||
所有主流平台、框架都遵循这一原则,且会主动拦截“子线程操作 UI” 的行为:
|
||||
1. Android
|
||||
- 主线程(UI 线程)通过 Looper 循环处理 MessageQueue 的 UI 消息
|
||||
- 子线程操作 UI 会直接弹出 `CalledFromWrongThreadException`(只有创建视图层次的原始线程才可以触摸其视图)
|
||||
- 必须通过 Handler、runOnUiThread、Croutine(Dispatch.Main)等方式更新 UI
|
||||
2. iOS
|
||||
- 主线程(UI 线程)通过绑定主 RunLoop,负责处理 UI 事件(点击、触摸、滑动)和渲染
|
||||
- 子线程操作 UI 可能导致界面异常(比如 UILabel 文本不更新)、甚至 crash
|
||||
- 必须通过 dispatch.async 来向主队列派发可以用于主线程执行的任务
|
||||
3. Web 前端
|
||||
- 浏览器的 DOM 操作是单线程的(主线程负责 DOM 渲染、事件处理)
|
||||
- 子线程(如 Web Worker)无法直接操作 DOM,必须通过 postMessage 通知主线程操作 UI 更新
|
||||
|
||||
总结:UI 必须在主线程上更新是因为:UI 控件没有设计线程同步机制(比如加锁),所以框架为了保证线程安全、状态一致、渲染高效,一刀切直接采用了单线程模型。
|
||||
|
||||
|
||||
### 1. 背景介绍
|
||||
|
||||
@@ -8263,27 +8309,8 @@ runZoned<Future<Null>>(() async {
|
||||
|
||||
## 十四、未来规划
|
||||
|
||||
- 监控能力继续完善
|
||||
|
||||
- 技术持续研究,提升监控准确度、案发第一现场数据,便于排查问题
|
||||
|
||||
- 监控能力继续完善、提升监控准确度
|
||||
- APM 新方向的研究。UI 自动化结合 iOS Instrucments Server 中的性能数据(DTXMessage 通信)
|
||||
|
||||
- 开源 SDK + 桌面端 App 查看性能数据(产品侧)
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [iOS 保持界面流畅的技巧](https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/)
|
||||
- [Call Stack](https://en.wikipedia.org/wiki/Call_stack)
|
||||
- [iOS 启动时间优化](https://www.zoomfeng.com/blog/launch-time.html)
|
||||
- [WWDC2019 之启动时间与 Dyld3](https://www.zoomfeng.com/blog/launch-optimize-from-wwdc2019.html)
|
||||
- [Apple-libmalloc](https://opensource.apple.com/tarballs/libmalloc/)
|
||||
- [Apple-XNU](https://opensource.apple.com/tarballs/xnu/)
|
||||
- [OOM 探究:XNU 内存状态管理](https://www.jianshu.com/p/4458700a8ba8)
|
||||
- [Reducing FOOMs in the Facebook iOS app](https://engineering.fb.com/ios/reducing-fooms-in-the-facebook-ios-app/)
|
||||
- [iOS 内存 abort(Jetsam) 原理探究](https://satanwoo.github.io/2017/10/18/abort/)
|
||||
- [iOS 微信内存监控](https://wetest.qq.com/lab/view/367.html?from=coop_gad)
|
||||
- [iOS 堆栈信息解析(函数地址与符号关联)](https://www.jianshu.com/p/df5b08330afd)
|
||||
- [Apple-CFNetwork Programming Guide](https://developer.apple.com/library/archive/documentation/Networking/Conceptual/CFNetwork/Introduction/Introduction.html#//apple_ref/doc/uid/TP30001132-CH1-DontLinkElementID_30)
|
||||
- [MDN-HTTP Messages](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages)
|
||||
- [DWARF 和符号化](https://junyixie.github.io/2018/09/30/dwarf和符号化/)
|
||||
- 产品侧:开源 SDK + mPaaS 平台(或者 Electron 写一款 桌面端 App 查看性能数据)
|
||||
- AI 赋能:根据特征数据做到智能化归因
|
||||
- 报警平台已具备波动报警、业务域 Owner 报警策略可配置。未来需利用 AI 能力做更多畅想
|
||||
|
||||
Reference in New Issue
Block a user