【Android 客户端专场 学习资料三】第四届字节跳动青训营

1,884 阅读25分钟

第四届字节跳动青训营讲师非常用心给大家整理了课前、中、后的学习内容,同学们自我评估,选择性查漏补缺,便于大家更好的跟上讲师们的节奏,祝大家学习愉快,多多提问交流~

第七节:初识性能优化及工具

课程概述

  • 为什么做性能优化?(why)
  • 性能优化是什么?(what)

    • 流畅性优化
    • 资源优化
    • 稳定性优化
    • 系统级优化
  • 最佳性能工具选型
  • 如何做性能优化?(how)

    • 性能优化三部曲
    • 性能拆解归因介绍
    • view构建优化案例分享
    • 解析优化案例分享
    • 异步渲染案例分享

课前

实践准备 (必须)

  • 利用GPU呈现模式工具,分析抖音、快手、微博主界面的性能差异
  • 进阶

课中

01 为什么要做性能优化

  • 了解性能优化与业务发展之间的关系

    • Android发展至今,各项基础设施非常完善的情况下,我们越来越重视App的性能优化,以及用户体验,这关乎一个线上应用的业务数据持续增长的基础,以及用户口碑的问题
  • PC平台和移动平台的硬件性能优化的发展历程

    • 通过x86平台和arm平台的发展历史,来展望性能优化
  • 在长时间的历史范围内看整体的优化趋势和软件优化能带来的优势

    • 硬件与软件的结合也是最佳的体验的基础
  • 用实际的例子介绍性能优化的必要性

    • Talk is cheap

\

02 性能优化是什么?

  • 2.1 性能优化的主要目标是什么

    • :最快显示效率、最快网络速率、最快UI响应
    • :最佳用户体验,减少强打断
    • :最低存储、最低功耗、最低流量消耗、最低计算资源

2.2 广义的性能优化分类

流畅度、资源、稳定性、系统级

2.3 流畅性优化基础介绍

Google 定义:界面呈现是指从应用生成帧并将其显示在屏幕上的动作。要确保用户能够流畅地与应用互动,应用呈现每帧的时间不应超过 16ms,以达到每秒 60 帧的呈现速度(为什么是 60fps?)。 如果应用存在界面呈现缓慢的问题,系统会不得不跳过一些帧,这会导致用户感觉应用不流畅,我们将这种情况称为卡顿。

思考:为什么是 60fps 或 16ms?

16ms 意味着 1000/60hz,相当于 60fps。这是因为人眼与大脑之间的协作无法感知超过 60fps 的画面更新。12fps 大概类似手动快速翻动书籍的帧率, 这明显是可以感知到不够顺滑的。24fps 使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。 24fps 是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。 但是低于 30fps 是 无法顺畅表现绚丽的画面内容的,此时就需要用到 60fps 来达到想要的效果,超过 60fps 就没有必要了。如果我们的应用没有在 16ms 内完成屏幕刷新的全部逻辑操作,就会发生卡顿。

2.4 资源优化基础介绍

  • 最大化资源调度:最大资源调度分为两个方向,第一个方向将一些有限资源尽量向最影响体验的方向靠拢,首先要满足,我们需要在网络、渲染等领域提供更多的资源。第二个方向,探寻更多的资源供给,首先要满足,深度剖析系统资源使用,需要从系统层榨取更多的可用资源,也需要从用户敏感角度榨取更多资源,最终实现最大化资源调度。
  • 最小化资源使用:需要对持续性的指标影响降到最低,首先要满足,我们对功耗、存储、流量等指标在一些用户敏感度大于实际获得的体验的环境下,保障核心功能的体验。本质的原则就是保证业务基本面的前提下,通过降级或者优化等手段,将占用的资源做到最小。
  • 2.5 稳定性优化基础介绍

    •   当性能劣化累积到一定程度,就变成了稳定性问题,直接强制打断应用的使用体验。

2.6系统级优化基础介绍

如何充分利用应用程序和系统程序,综合提升应用的性能表现。有哪些可以挖掘的点。

03 最佳工具选型

3.1 性能监控工具的价值

App的性能问题包括崩溃、网络请求错误或超时、响应速度慢、列表滚动卡顿、流量大、耗电等等。而导致App性能低下的原因有很多,除去设备硬件和软件的外部因素,其中大部分是开发者错误地使用线程、锁、系统函数、编程范式、数据结构等导致的。即便是最有经验的程序员,也很难在开发时就能避免所有导致性能低下的“坑”,因此解决性能问题的关键是在于能不能尽早地发现和定位这些“坑”。

  • 3.2 Gpu呈现模式

    • 在图 1 中显示的 GPU 渲染模式分析图形的放大图像中,您可以看到 Android 6.0(API 级别 23)上显示的彩色部分。

      •     图 1. 放大的 GPU 渲染模式分析图形。

下面是有关输出的几点注意事项:

  • 对于每个可见应用,该工具将显示一个图形。
  • 沿水平轴的每个竖条代表一个帧,每个竖条的高度表示渲染该帧所花的时间(以毫秒为单位)。
  • 水平绿线表示 16 毫秒。要实现每秒 60 帧,代表每个帧的竖条需要保持在此线以下。当竖条超出此线时,可能会使动画出现暂停。
  • 该工具通过加宽对应的竖条并降低透明度来突出显示超出 16 毫秒阈值的帧。
  • 每个竖条都有与渲染管道中某个阶段对应的彩色区段。区段数因设备的 API 级别不同而异。

下表介绍了使用运行 Android 6.0 及更高版本的设备时分析器输出中某个竖条的每个区段。

Layertool

抖音自研工具,快速识别图层及过度绘制、绘制区域过大等问题,提升整体渲染效率.

CPU Profiler

如需打开 CPU 性能剖析器,请按以下步骤操作:

  1. 依次选择 View > Tool Windows > Profiler 或点击工具栏中的 Profile 图标
  1. 如果 Select Deployment Target 对话框显示提示,请选择需将您的应用部署到哪个设备上以进行性能剖析。如果您已通过 USB 连接设备但系统未列出该设备,请确保您已启用 USB 调试
  1. 点击 CPU 时间轴上的任意位置以打开 CPU 性能剖析器。
  • 当您打开 CPU 性能分析器时,它会立即开始显示应用的 CPU 使用率和线程活动。系统会显示类似于图 1的界面。
    •   图 2. CPU 性能分析器中的时间轴。

如图 2 所示,CPU 性能分析器的默认视图包括以下时间轴:

  1. 事件时间轴:显示应用中的 activity 在其生命周期内不断转换经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。如需了解如何在搭载 Android 7.1(API 级别 25)及更低版本的设备上启用事件时间轴,请参阅启用高级性能分析功能
  1. CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还会显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的 CPU 使用率进行对比。您可以通过沿时间轴的横轴方向移动鼠标来检查历史 CPU 使用率数据。
  1. 线程活动时间轴:列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录轨迹后,您可以从此时间轴上选择一个线程,以在轨迹窗格中检查其数据。

    1. 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,线程处于正在运行或可运行状态。
    2. 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
    3. 灰色:表示线程正在休眠且没有消耗任何 CPU 时间。 当线程需要访问尚不可用的资源时,就会出现这种情况。在这种情况下,要么线程主动进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用。
  1. CPU 性能分析器还会报告 Android Studio 和 Android 平台添加到应用进程的线程的 CPU 使用率,这些线程包括 JDWPProfile SaverStudio:VMStatsStudio:PerfaStudio:Heartbeat 等(不过,它们在线程活动时间轴上显示的确切名称可能有所不同)。Android Studio 报告此数据是为了方便您确定线程活动和 CPU 使用率什么时候是由应用的代码实际引发的。

TraceView

如需通过 Android Studio 中的 Traceview 打开跟踪日志,请按以下步骤操作:

  1. 启动 Android Device Monitor
  1. 在 Android Device Monitor 中,依次选择 File > Open File。
  1. 转到您要检查的 .trace 文件。
  1. 点击 Open。

打开跟踪日志后,Traceview 会使用以下两个窗格显示日志数据:

  • 剖析窗格,总结每个线程在跟踪日志期间的执行情况

以下各部分进一步介绍了 Traceview 的输出窗格。

时间轴窗格

  • 图3显示了时间轴窗格的特写。每个线程的执行情况都显示在各自的行中,并且越往右使用的时间越长。每个方法都以不同的颜色显示。第一行下面的细线显示所选方法的子级(从进入到退出)。
    •   图 3. Traceview 时间轴窗格。

分析窗格

如图 4 所示,剖析窗格列出了跟踪日志期间执行的各个方法以及执行这些方法所用的时间。调用另一个方法的方法称为父级,父级调用的方法称为其子级。当您通过点击某个方法以选择该方法时,它会在两个单独的节点下同时显示其父级和子级。

对于每个方法(顶级节点),该表会显示其非独占时间和独占时间(以毫秒为单位)以及占总时间的百分比。独占时间是执行方法自身代码所用的时间,而非独占时间则是执行方法自身代码所用时间与执行其子级代码所用时间之和。系统还会根据 CPU 时间和实际时间报告用时信息。CPU 时间仅考虑线程主动使用 CPU 的时间,而实际时间则提供从应用进入方法到退出该方法这整个过程(无论线程处于活动状态还是休眠状态)的绝对用时信息。

  • 对于分析窗格中的每个顶级节点,表中的 Calls + Rec, Calls/Total 列(图 4 中未显示)会报告对相应方法的调用次数和递归调用的次数。而对于父方法和子方法,此列会显示被调用方法为顶级节点中方法的子级或父级的调用次数。
    •   图 4. Traceview 分析窗格。

Systrace

systrace 命令会调用 Systrace 工具,您可以借助该工具收集和检查设备上在系统一级运行的所有进程的时间信息。

本文档说明了如何通过命令行生成 Systrace 报告。在搭载 Android 9(API 级别 28)或更高版本的设备上,您还可以使用“系统跟踪”系统应用生成 Systrace 报告。

如需运行 systrace,请完成以下步骤:

  1. 从 Android Studio 下载并安装最新的 Android SDK 工具
  1. 安装 Python 并将其添加到工作站的 PATH 环境变量中。
  1. android-sdk/platform-tools/ 添加到 PATH 环境变量。此目录包含由 systrace 程序调用的 Android 调试桥二进制文件 (adb)。
  1. 使用 USB 调试连接将搭载 Android 4.3(API 级别 18)或更高版本的设备连接到开发系统。

systrace 命令在 Android SDK 工具软件包中提供,并且可以在 android-sdk/platform-tools/systrace/ 中找到。

语法

如需为应用生成 HTML 报告,您需要使用以下语法通过命令行运行 systrace

python systrace.py [options] [categories]

例如,以下命令会调用 systrace 来记录设备活动,并生成一个名为 mynewtrace.html 的 HTML 报告。此类别列表是大多数设备的合理默认列表。

$ python systrace.py -o mynewtrace.html sched freq idle am wm gfx view \
        binder_driver hal dalvik camera input res
    

提示:如果要在跟踪输出中查看任务名称,必须在命令参数中添加 sched 类别。

如需查看已连接设备支持的类别列表,请运行以下命令:

$ python systrace.py --list-categories

如果您未指定任何类别或选项,systrace 会生成包含所有可用类别的报告,并使用默认设置。可用类别取决于您所使用的已连接设备。

全局选项

命令和命令选项

命令和选项说明
-o file将 HTML 跟踪报告写入指定的文件。如果您未指定此选项,systrace 会将报告保存到 systrace.py 所在的目录中,并将其命名为 trace.html。
-t N--time=N跟踪设备活动 N 秒。如果您未指定此选项,systrace 会提示您在命令行中按 Enter 键结束跟踪。
-b N--buf-size=N使用 N KB 的跟踪缓冲区大小。使用此选项,您可以限制跟踪期间收集到的数据的总大小。
-k functions--ktrace=functions跟踪逗号分隔列表中指定的特定内核函数的活动。
-a app-name--app=app-name启用对应用的跟踪,指定为包含进程名称的逗号分隔列表。这些应用必须包含 Trace 类中的跟踪检测调用。您应在分析应用时指定此选项。很多库(例如 RecyclerView)都包括跟踪检测调用,这些调用可在您启用应用级跟踪时提供有用的信息。如需了解详情,请参阅定义自定义事件。如需跟踪搭载 Android 9(API 级别 28)或更高版本的设备上的所有应用,请传递用添加引号的通配符字符 "*"。
--from-file=file-path根据文件(例如包含原始跟踪数据的 TXT 文件)创建交互式 HTML 报告,而不是运行实时跟踪。
-e device-serial--serial=device-serial在已连接的特定设备(由对应的设备序列号标识)上进行跟踪。
categories包含您指定的系统进程的跟踪信息,如 gfx 表示用于渲染图形的系统进程。您可以使用 -l 命令运行 systrace,以查看已连接设备可用的服务列表。

btrace-进阶

\

Battery Historian

github.com/google/batt…

如需使用 Batterystats 从您的设备收集数据并在 Battery Historian 中打开该数据,请执行以下操作:

  1. 将移动设备连接到计算机。
  1. 在终端窗口中,关闭正在运行的 adb 服务器。
adb kill-server
  1. 重启 adb 并检查是否有已连接的设备。
adb devices

系统应该会列出您的设备,类似于下面的示例输出。

图 2. adb devices 的输出,显示一个已连接的设备

如果您没有看到任何设备,请确保您的手机已连接,且 USB 调试功能已开启,然后终止并重启 adb。

  1. 重置电池数据收集。
adb shell dumpsys batterystats --reset
    

设备始终会在后台收集 Batterystats 和其他调试信息。重置操作会清除旧的电池收集数据。如果不重置,输出内容会非常大。

  1. 断开设备与计算机的连接,以便仅消耗设备电池的电量。
  1. 使用您的应用并执行您想要获取数据的操作;例如,断开 WLAN 连接并将数据发送到云端。
  1. 重新连接手机。
  1. 确保系统已识别您的手机:
adb devices
  1. 转储所有电池数据。此过程可能需要一段时间:
    adb shell dumpsys batterystats > [path/]batterystats.txt

系统会使用可选路径参数在您指定的目录中创建 batterystats.txt 文件。如果您没有指定路径,该文件会在您的主目录中创建。

  1. 使用原始数据生成报告。

对于搭载 Android 7.0 及更高版本的设备:

adb bugreport [path/]bugreport.zip

对于搭载 Android 6.0 及更低版本的设备:

adb bugreport [path/]bugreport.txt

错误报告可能需要几分钟才能完成。在完成之前,请勿断开设备连接或取消该进程。

与上面的 batterystats.txt 一样,这些文件是系统使用可选的 path 参数在您指定的目录中创建的。如果您没有指定路径,系统将在您的主目录中创建这些文件。

如果 Battery Historian 尚未运行,请使用以下命令运行:

    docker --run -p port_number:9999 gcr.io/android-battery-historian:2.1 --port 9999   
  1. 如需在 Battery Historian 中查看数据,请在浏览器中打开 Battery Historian。(对于 Mac 和 Linux,Battery Historian 在 http://localhost:port_number 运行。对于 Windows,Battery Historian 在 http://your_IP_address:port_number 运行。)
  1. 点击 Browse,然后选择您在上面创建的错误报告文件。
  1. 点击 Submit。Battery Historian 将打开您根据 Batterystats 数据创建的图表。

\

\

补充说明

可以使用两个工具查看systrace和btrace的生成文件,请使用chrome浏览器打开:

chrome://tracing/

perfetto.dev/

  • Perfetto 是 Android 10 中引入的全新平台级跟踪工具。这是适用于 Android、Linux 和 Chrome 的更加通用和复杂的开源跟踪项目。与 Systrace 不同,它提供数据源超集,可让您以 protobuf 编码的二进制流形式记录任意长度的跟踪记录。您可以在 Perfetto 界面中打开这些跟踪记录。
    •   图 1. Perfetto 跟踪记录视图示例,其中显示了与某个应用之间大约 20 秒的交互情况
    •   图 2. Systrace HTML 报告示例,其中显示了与某个应用之间 5 秒的交互情况

这两份报告都提供了 Android 设备在给定时间段内的系统进程的总体情况。该报告还检查了捕获到的跟踪信息,以突出显示发现的问题(例如界面卡顿或耗电量高)。

Perfetto 和 Systrace 可交互使用:

  • 在 Perfetto 界面中打开 Perfetto 文件和 Systrace 文件。在 Perfetto 界面中使用旧版 Systrace 查看器打开 Systrace 文件(使用 Open with legacy UI 链接)。

\

04 性能优化技术案例

4.1 现状分析

4.1.1 耗时拆解

  1. CPU Time 指占用CPU进行计算所花费的时间绝对值,中断、挂起、休眠等行为是不会增加CPU Time的,所以因CPU Time开销占比高导致的不合理耗时点往往是逻辑本身复杂冗长需要消耗较多cpu时间片才能处理完。比较常见的高CPU占用是循环,比如抖音启动时遇到过一个so加载耗时,最后定位原因是在解压so的时候,遍历ZipEntry的次数过多导致,一个可行的优化策略就是可以把so所在的ZipEntry提前,遍历完so的ZipEntry之后可以提前中止遍历,而不需要遍历剩下的无效ZipEntry。
  1. CPU Schedule 在分析时主要针对主线程,是指主线程处于可执行状态但获取不到cpu时间片,这类耗时可能和线程调度等有关,最终导致分配给主线程的cpu时间片不足以及时处理完其内任务。由于主线程的线程优先级比其他线程的优先级要高很多,通常影响并不大,事实上抖音做了线上用户的启动耗时统计,这部分的耗时占比也是不大的。不过有一个场景需要关注,就是渲染,渲染是需要RenderThread提交GPU的渲染命令,而RenderThread并没有主线程那么高的优先级,因此比较容易受CPU的负载的影响,导致渲染耗时。
  1. IO Wait 指发生了IO操作需要等待IO返回结果,这类耗时可能发生在读取资源和文件,类加载,甚至在内存不足时的PageFault都会导致IO Wait。
  1. Lock Wait 也是主要针对主线程,指其处于等锁状态,等待被其他线程唤醒或自己超时唤醒,导致这类耗时的问题种类多样,大体也是可以分为业务锁和系统锁,业务锁主要是被主线程等待的业务逻辑未能及时处理完,优化思路一般是移除主线程的锁等待逻辑或者加快被等待的业务逻辑的执行速度。系统锁主要有:String InternTable Lock,ClassLinker Lock,GC Wait Lock等
  1. IPC 指进程间通信,操作系统大都含有相应的机制,Android中所特有的IPC机制是Binder,由于进行IPC调用往往需要等待通信结果本质上这也算是一种Lock Wait,但Android特有Binder机制所以单独列出,这类耗时可采用减少或替代Binder调用等手段来优化。

4.1.2 运行环境归因

  • 前台运行
  • 后台运行

4.1.3抖音启动分析

列举了抖音的整体的启动耗时拆解及优化策略

4.1.4 渲染分析及耗时归因

4.1.5 从任务角度和耗时角度拆解一帧的耗时

4.2 优化案例分享

  • 4.2.1 拆解View显示流程中的耗时成因

    • UI 构建

      • 在UI构建阶段中首先要对界面布局的xml文件进行解析,这会导致IO Wait耗时,在接下来要解析xml文件中的TagName从而获取对应View的class会用到反射、创建各子View实例并生成View树又会用到循环递归,两部分都会增加CPU Time的开销。
    • 数据绑定

      • 然后是数据绑定阶段,该阶段主要分两部分,一部分是对数据做请求、解析、适配,另一是部分是将适配好的数据填充进UI中,前一部分往往会涉及到Json解析成Data Class实例,这里就可能涉及反射、循环遍历嵌套的数据类结构等增加CPU Time的操作。
    • View显示

      • 最后是View显示阶段,常见的measure、layout、draw三大渲染View的步骤就在其中,它们同样会产生递归遍历父子View的耗时,此外这里还涉及将应用层计算好的渲染View的数据传递给系统层做最终的像素点排布,那么必然又会产生IPC耗时

4.2.2 UI构建的优化方案

developer.android.com/reference/a…

4.2.3 数据绑定的优化方案

4.2.4渲染和布局优化方案

系统工具查看具体的overdraw情况,但并不能细化到具体的布局和位置,我们开发了LayerTool工具可以根据自定义需求过滤各个布局,然后在界面上提示对应的位置,可以有效的查找导致overdraw的布局。我们通过LayerTool工具查看哪些布局导致了过度绘制。然后我们可以逐个开始优化:

  • 移除不必要的背景图 :去除冗余背景
  • 修改不合理布局:精细化布局显示
  • 写高效合理的布局:随着状态的变换,及时调整布局的绘制背景
  • 移除默认的 Window 背景 :Activity其实是有一层默认背景windowBackground。如果需要做到极致的优化,可以考虑将windowBackground设置为空,但是同时需要处理好随之而来的各种问题。主要包括:把windowBackground设置为空后,如果有某些View没有设置背景,就会出现花屏/重影的现象。

4.2.5 渲染优化的异步化方案

如何彻底解决主线程的阻塞问题:

课后

  1. 自己实现一个LayerTools
  1. perfetto.dev/ 分析一个你自己编写的app

参考资料

第八节:打开 ART 虚拟机的大门

课程概述

安卓整体架构

下图中黄色的部分,就是ART,给APP和system server进程提供运行环境,包括JAVA语法支持,托管,性能优化,debug等等一系列的能力。

\

ART架构

ART可以粗略的划分成两个层级,执行层和runtime层,执行层负责直接面向java代码的产物,来翻译或者编译执行。runtime层则是提供java语法特性和其他一些支撑运行的底层机制。

课前

我们了解安卓ART虚拟机之前,做一些适当的准备工作:

1.环境准备

安卓android studio,尝试做个test app:developer.android.com/studio

2.了解AOSP

Android developer:developer.android.com/

AOSP: source.android.com/

Android架构:source.android.com/devices/arc…

ART代码: cs.android.com/android/pla…

3.JAVA语法

基本语法:www.runoob.com/java/java-b…

Java language spec:docs.oracle.com/javase/spec…

JVM spec:docs.oracle.com/javase/spec…

课中

课程包含两条主线:

  • 我们的对象是怎么分配出来的?
  • 虚拟机为了保证我们的代码高效顺利执行,需要提供哪些机制?

1.对象

  • 对象分配的大小怎么确定的 -类
  • 对象怎么分配的 - 内存分配
  • 对象怎么回收 - 内存回收

对象大小-类

对象和类结构

juejin.cn/post/695092…

classloader&双亲继承

www.jianshu.com/p/27d08bd27…

动动手:尝试做一个双亲继承的demo case,看下定义一个相同包名+类名的类,能否覆盖掉原有的framework的类?

内存分配

内存碎片

blog.csdn.net/weixin_4695…

动动手:在testapp中,分配10KB * 100000,和100M * 10,看看是否都能顺利申请到?

LinkedList<byte[]> mylist = new LinkedList<>();
for(int i = 0; i < 100000; i++) {
    mylist.add(new byte[10*1024]);
}

分配算法

伙伴算法:zhuanlan.zhihu.com/p/321780626

TLAB:heapdump.cn/article/222…

内存回收

GC演进:codeantenna.com/a/wwkwmFn5j…

回收算法:www.openjq.com/thread-2914…

进阶算法:liujiacai.net/blog/2018/0…

动动手:能分配一个弱引用,一个软引用,然后强制gc,观察是否为空

String softString = new String("soft");
SoftReference<String> mySoftRef = new SoftReference<>(softString);

String weakString = new String("weak");
WeakReference<String> myWeakRef = new WeakReference<>(weakString);

System.gc();

//get看看mySoftRef myWeakRef

2.执行

  • 执行包括哪些方式 - JIT/AOT/解释
  • 栈管理
  • 异常处理
  • 多线程

下面有每个内容的一些补充的文章:

执行方式

字节码格式:source.android.com/devices/tec…

动动手:使用dexdump,jd-gui解析一个apk java-decompiler.github.io/

栈管理

ARM的调用规则:developer.arm.com/documentati…

异常

www.codeleading.com/article/561…

多线程

spink&mutex区别: developer.aliyun.com/article/104…

锁介绍:juejin.cn/post/695621…

课后

下课了,醒醒。

\

第九节:客户端架构设计及应用

课程概述

首先,本课程不是一个编码实践课程,而是架构理论和模型的概述。

然后,架构面临着很多问题,也有一些应对手段,本课程将会讲解常见的架构手段。

接着,一个架构演进的例子,描述一个产品在生命周期的不同阶段,架构如何变化。

最后,希望大家勤于思考和编码,保持技术热情,成为一个有追求的架构师。

\

课前

思考几个小问题

1.你所了解的架构是什么?

2.你有一些生活中要用到架构设计的例子吗?

3.你觉得架构师们每天都在干什么?

课中

架构面临的问题

•架构设计是为了解决特定领域不同发展阶段的业务问题

•不同领域的架构有明显的技术差异,但也有很多相似性

•架构不仅面临技术挑战,还要应对组织业务膨胀的熵增

•移动端需要利用有限的设备资源设计符合小屏幕的架构

常见的架构手段

•不同架构手段的共同目标是高内聚低耦合

•找到适合业务场景的架构而不是炫技滥用

•一个复杂的系统是多种架构模型的组合体

架构演进的例子

•架构随业务发展由简单变得复杂是规律

•没必要最初用复杂架构来解决简单问题

•需要用规范持续重构来对抗代码的腐朽

成为优秀架构师

•定义问题 → 确定架构 → 方案落地 → 结果复盘

•架构的问题是盘根错节的,将所有问题放在一起,就有轻重缓急之分,就有类别之分

•挑战、问题、手段这些经常混为一谈,哪些是挑战?哪些是问题?那些是手段?

•勤于编码,有技术追求

课后

写一个头条试试,^-^

\

第十节:成为一名好 RD,你该具备的研发素养

课程概述

本课程从代码质量、代码评审、重构、代码上线几个角度分享了一个优秀的研发同学,应当具备的基本素养。

\

课前

思考几个小问题

1.你有给别人做过Code Review吗?你关注哪些代码问题?

2.你做过代码重构吗?

\

课中

代码质量

1.小小的代码错误,可酿成巨大的损失

2.优秀的代码可信赖、易维护、Bug少

3.面对庞大的代码需遵循可维护性规则

4.圈复杂度作为度量工具的计算和用途

\

代码评审

1.CR能前置地发现代码质量问题

2.将CR做得小点能加快评审效率

3.谦逊坦诚面对不同的评审意见

\

CR的一个实例

\

重构实践

1.代码中常有技术债,理解它,处理它

2.重构是在有限范围内运用一定的方法

\

\

代码上线

•分支开发模式

•持续集成概念

•灰度发布

•AB实验