个人项目 总结

性能优化

  • 首帧优化 - 打点统计分析,组合类初始化后置, playerURL前置, 聚合接口、播放器缓存复用(从直播间A-B)
  • 卡顿优化 - 弹幕互动区优化
    • 刷新频率控制
    • 后台线程计算布局+draw (coregraphics)
    • coreText
  • 泄漏优化
    • 内存泄漏小工具检测
    • 野指针监测工具
  • 缓存策略 (缓存做了分类管理、如资源缓存-皮肤、图片缓存、播放器缓存)
    • 在线资源缓存、如giftImage、全屏动效、直播间换肤、与h5通信的数据存储等
    • 列表的数据缓存 (YYcache)
  • 多线程计算、队列的处理
    • 比如计算、队列分发等
  • 动画性能检测
    • 做个svga检测小工具,检测全屏动画对手机性能影响,iphone6s,FPS <40、CPU>100% 内存>40m。 通过charts第三方库输出曲线图,超出标红线

包体积优化

  • mach-o text优化
    • linkMap file分析
    • 根据mach-o,text里的classmethod和使用的classmethodref做过滤,剔除无用方法
    • 代码复用 - 如ipad改版、三套代码聚合
    • 属性换变量
    • masonry的block替换、@weakify替换等
  • 资源瘦身
    • 资源优化 - 大图下发、unuse图检查删除、删除图片附属信息+压缩、gif转webp、 AssetCataLog管理
    • 静态UIh5化 -
    • 依赖优化 - 相似代码检查+合并、编译可见域删选(DEBUG)
    • 代码优化 - 抽离公共组件或base层提高代码复用、UI布局替换、 细节(readonly string、property->IVar、宏替换检查等)
    • 其他 linkmap file 分析
    • otool 构建引用图、查找孤立点
    • Clang Plugin分析AST优化引用
  • 自动化工具
    • 自动化压缩
    • gif转webp
    • 图片分辨率扫描
    • unused 检查
    • assets 资源大小统计
    • 相似图片扫描 (基于 image hash)

直播间架构设计

  • 层级架构
    • 直播间容器简单分成了6层、content、player、panel、halfcontainer、effect(特效层)、弹窗层
    • 各类业务加在对应层级上,互不干扰
    • 特殊场景,半、全屏切换时(只发生在横屏直播间),业务层级变化由直播间容器通知并切换 如运营位、pk大乱斗业务、醒目留言业务等
    • 手势透传 直播间的view基本继承自定义的手势透传view,这样无论层级有多少层,只要不响应事件,均能往下透传
  • 组件化
    • 常用方法统一化(去重):宏定义、category统一收口 (当时还有代码规范、review方案等)
    • 通用的基础能力组件化:队列管理(优先级)、mutableDelegate 环境变量配置、数据存储、用户信息(登录态)、(网络配置)、缓存、GCDTimer等
    • 通用业务+UI组件化:logger、segmentController、跑马灯、toast、alert、空视图、等
    • 常规业务模块化:比播放器、面板、弹幕互动区、礼物、公告、关注、榜单、大航海、pk等
      1. 模块收敛,把人为认为属于同一模块的东西合并在一起
      2. 数据去依赖,聚合接口吐完数据,转成我模块内需要的数据,传递
      3. 去胶水代码(只保留和容器或领域的,其他均删除,事件通过回调或内部处理)
      4. 治理直播间容器的调度,采用可插拔的形式集成各个模块
      5. 针对老旧、或需要新大改的的模块进行MVVM重构或ddd重构,大模块内部单独再单独设计(比如礼物模块内部集成了面板/全屏动画/webview/连击条/付费留言等子业务).
    • ddd领域驱动建设(搞了一半),
      1. 要先将数据层抽离干净,然后将数据分成用户、房间、抽奖活动域,基于此上层再吧各个业务抽象化,
      2. 根据各个业务不同,领域提供service和parser来做数据层驱动,接入基础数据域,通过configuration来配置初始化。通信、回调只能通过领域
      3. 领域内部的视图管理还是采用的mvvm结构。领域有子域的概念,领域内的子域属于内嵌的关系。领域内的埋点尽量可以抽离,做无痕埋点,领域与领域直接的通信则依赖直播间容器。

屏幕适配(ipad适配)

难点:1. 分屏播放后,转到全屏, 保证效果跟手机一致,流不断。并前后数据上报不重复。
    2. 代码如何复用、跳转如何处理

终端日志

分三块、日志存储、日志回捞、日志接入。其中基于优先级控制打印力度 基于DDLog,自定义存储大小4m和保存日期7d,配置存储路径(基于uid),log内部无感知加入时间、cmd、line等 回捞配置包括两部分:等级下发(uid、生效时间段+等级)、日志回捞(包括uid、回捞时间段+offset) 监控:网络切换、用户登录态、各种异常失败(关注、送礼失败(多端登录情况)、数据解析异常,如大乱斗)、接口监控、apm、资源加载异常监控、核心场景和流程链路监控(播放器异常等)

配置平台

  1. 基于task的key、value配置平台
  2. 客户端任务分发模式
  3. 半增量下发 基于hash
  4. task绑定abtest、uid、尾号(特定用户群里)、版本、机型、时效性、地区控制等,并配上主体body(k-v),服务端根据条件过滤k-v,并做去重,生成hash、缓存、下发客户端
  5. 客户端请求带上业务id+hash、成功后分发任务

runtime的应用

  • 消息转发:多代理、应用配置、jsbridge交互、、跨模块通信(不推荐)
  • runtime:hook、基于协议的偏好配置(获取协议属性列表、生成set和get方法存入列表,再根据运行时消息转发判断方法是否在方法列表里)、同理也应用在埋点上(
  • protocol_copyProtocolList(protocol, &protocolCount)
  • objc_property_t *properties = protocol_copyPropertyList(protocol, &propertyCount)
  • protocol_copyAttributeValue(property, “G”)
  • 等等)

runloop的应用

  • 线程保活 很早之前socket方案
  • timer
  • 卡顿检测
  • 大数据遍历处理,比如礼物配置信息,头衔列表信息
  • 监听runloop的beforwarting,进行数据处理。避免高风险卡顿(比如feed流里的setimage方法)
  • 某些一定要需要获取的接口,(类似线程保活)