Qcon2017参会总结
今年有幸参加了在北京国家会议中心的举办的qcon技术盛宴,这也是我第一次相关的技术论坛,受益颇丰,特此记录。
概览
大会议题盛多,几乎涵盖了技术的方方面面。时间精力有限,本人此次参会主要关注移动端的相关议题,并参与了其他若干刚兴趣的话题。
本人主要参与的分享包括:
- 移动端
- 腾讯手游性能优化之路 – 何纯
- iOS App内存专项实践:封闭系统下的大自由 – 黄闻欣
- 网易乐得“无埋点”数据采集实践之路 – 庞辉
- 去哪儿网快速App开发及问题解决平台实践 – 张子天
- VirtualAPK:滴滴出行Android插件化方案 – 任玉刚
- React Native在移动应用研发中的全量化实践 – 陈敏亮
- 微信移动客户端数据存储优化实践 – 凌国
- 其他议题
- 经典算法与深度学习在百度外卖物流调度中的应用 – 徐明泉
- 今日头条推荐系统架构设计实践 – 金敬亭
- 代码未写,漏洞已出——谈谈设计不当导致的安全问题 – TK教主(于旸)
- 万亿级数据洪峰下的消息引擎——Apache RocketMQ – 王小瑞(誓嘉)
- 3x3:提速移动交付 – 胡克秋
分享概览
腾讯手游性能优化之路
- 手游性能问题
- 卡顿(FPS/CPU/GPU/drawcall)
- 发热(CPU/GPU)
- 耗电(CPU/GPU)
- 延迟(CPU/网络IO)
- 瞬移(网络IO/延迟)
- 闪退(内存)
- 数据获取方案
- PSS内存(/proc/self/smaps)
- 网络流量(/proc/net/xt_qtaguid/stats)
- mono内存(mono_stack_walk_no_il、mono_object_get_size)
- drawcell(glDrawArrays、glDrawElements、……)
- FPS(swapbuffer)
- CPU(/proc/stat、/proc/self/stat)
- 三角形数量(glDrawArrays、glDrawElements、……)
- GPU(/sys/class/kgsl/kgsl-3d0/gpubusy)
- 测试方案
- 大量机器人同屏释放技能
- 单人游戏
- 多人组队游戏
- 自动化测试
- 性能标准
- 腾讯手游TDR机型
- IOS
- 一档机型:iPhone 6S
- 二档机型:iPhone 6
- 三档机型:iPhone 5s
- 安卓
- 一档机型:R9/P9
- 二档机型:MI4/Mate8
- 三档机型:红米Note1S
- IOS
- 腾讯手游TDR机型
- 手游APM(Application Performance Monitor)
整个APM的意义: 测试方案确定 -> 原始性能数据 -> 指标性能数据 -> 性能问题监控 -> 性能问题排查 ->
iOS App 内存专项实践:封闭系统下的大自由
Xcode + Instruments是iOS系统下的使用最广泛的工具组合了,优点很明显,就是苹果原生支持,在开发模式下是最佳的性能调优工具,没有之一。但缺点也比较明显,一般仅限开发使用,自动化、CI都没法结合。
内存问题
VCLEAKDETECTOR
工作原理:
1. RefWatcher.watch() 创建一个 KeyedWeakReference 到要被监控的对象。
2. 然后在后台线程检查引用是否被清除,如果没有,调用GC。
3. 如果引用还是未被清除,把 heap 内存 dump 到 APP 对应的文件系统中的一个 .hprof 文件中。
4. 在另外一个进程中的 HeapAnalyzerService 有一个 HeapAnalyzer 使用HAHA 解析这个文件。
5. 得益于唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位内存泄漏。
6. HeapAnalyzer 计算 到 GC roots 的最短强引用路径,并确定是否是泄漏。如果是的话,建立导致泄漏的引用链。
7. 引用链传递到 APP 进程中的 DisplayLeakService, 并以通知的形式展示出来。
** android 80%的内存Bug都是演变成Activity泄漏 **,所以该方案在android上的实际功效是很大的。
倾情推荐:
** iOS的内存bug导致view泄露的比例并没有android高,iOS需要更高级的技巧 **
QQLeak
什么是内存泄露?
工作原理:
-
获取新建对象申请的内存地址与堆栈
- Hook OC: method_exchangeImplementations接管alloc,dealloc
- C++ 内 版本:借开发工具的权限,malloc_logger简单直接 (MallocStackLogging环境变量,每次内存分配都会打日志)
- C++ 外 版本:fishhook hook:malloc, calloc, free
-
获取指针变量
遍历堆区、全局区、栈区的指针变量
-
比较即可
OOMDetector
工作原理
- 记录申请的内存和堆栈
- 记录其释放
- 按照堆栈聚合数据
- 指标判断,单个申请的内存块大于50MB/申请内存(未释放)的总和大于阈值
机型 | 阈值 |
---|---|
4/4s | 200Mb |
5/5s/6/6s | 300Mb |
se/6s/6sp/7/7p | 800Mb |
内存越界
基于Xcode工具 Address Sanitizer。
问题一 3.4倍内存占用导致Jetsam
- 7s,内存大呀,20分钟后CRASH
- 模拟器跑,改造monkey适配模拟器
问题二 越界马上crash
- 增加参数-continue-after-error
- monkey记录跑过的路径
网易乐得 “无埋点”数据采集实践之路
收集策略
基于页面点击的AOP全量收集
- 页面事件全量收集
- 点击事件全量收集
基于KVC的业务数据收集
列表浏览量按需配置收集
- 只关注列表元素浏览量:行元素曝光量、停留时间
- 只上传KVC配置的列表元素:列表统计指标和内容结合分析
- 只统计停留时间较长的行元素:停止滑动时收集
页面点击唯一定位
page + xPath + 交互内容
难点解决
page
- 子页面处理,解决子页面结构不统一问题
- 页面别名,解决VC/Activity重用问题
xpath
xPath = viewPath+depthPath + (#id)
- viewPath:点击view的 响应者链条
- depthPath:按class分类,取 同类元素 的顺序Id + 列表处理(ios.indexpath)
e.g.
iOS: JCZQBettingController-UIScrollView-UITableView-UITableViewWrapperView-JCZQSPFCell-UITableViewCellContentView-UIImageView-UIButton&0-0-0-0-0:0-0-0-0
Android: DecorView/LinearLayout[0]/FrameLayout[0]/RelativeLayout[0]/TabHost[0]/RelativeLayo ut[0]/FrameLayout[0]/DecorView[0]/LinearLayout[0]/FrameLayout[0]/LinearLayout[0]/CP RefreshableView[0]/ListView[0]/LinearLayout[- 1,1]/LinearLayout[0]/LinearLayout[0]/FrameLayout[0]/LinearLayout[0]#card_panel
- 动态Add Fragment优化,fragment对应View节点名 = fragment类名
特殊case处理
- 弹窗问题
- 找当前最上层显示的Controller / Activity
- 自动获取弹窗标题+content
核心实现
也可以做RN,无非就是实现页面事件和点击事件入侵。策略几乎是一样的。
总结一下
不靠谱