关于性能的更多思考
什么是性能?
#性能是一组可量化的执行者属性。
在此语境下,性能本身并非指执行一个动作;而是指某事物或某人执行得如何。因此,我们使用形容词“高性能的”。
虽然“执行得如何”这部分通常可以用自然语言描述,但在我们有限的范围内,重点关注的是可以作为实数量化的内容。实数包括整数和 0/1 二进制作为特例。自然语言描述仍然非常重要。例如,一篇新闻文章仅使用文字(而非任何数字,即可量化的值)严厉批评 Flutter 的性能,仍然可能是有意义的,并且可能产生巨大影响。之所以选择有限的范围,仅仅是因为我们的资源有限。
描述性能所需的量通常被称为指标。
为了应对无数的性能问题和指标,您可以根据执行者进行分类。
例如,本网站上的大部分内容都关于 Flutter 应用性能,其中执行者是 Flutter 应用。基础设施性能对 Flutter 也非常重要,其执行者是构建机器人和 CI 任务运行器:它们极大地影响了 Flutter 整合代码更改的速度,从而提高了应用的性能。
此处,范围有意扩大到包括除应用性能问题以外的其他性能问题,因为无论执行者是谁,它们都可以共享许多工具。例如,Flutter 应用性能和基础设施性能可能共享相同的仪表板和类似的警报机制。
扩大范围还可以包含传统上容易被忽略的执行者。文档性能就是一个例子。执行者可以是 SDK 的 API 文档,指标可以是:发现 API 文档有用的读者百分比。
为什么性能很重要?
#回答这个问题不仅对于验证性能方面的工作至关重要,而且对于指导性能工作以使其更有用也很重要。“为什么性能很重要?”的答案通常也是“性能如何有用?”的答案。
简单来说,性能之所以重要且有用,是因为在该范围内,性能必须具有可量化的属性或指标。这意味着:
- 性能报告易于理解。
- 性能歧义性小。
- 性能具有可比性和可转换性。
- 性能是公平的。
这并不是说非性能问题或不可衡量的 issue 或描述不重要。它们旨在突出性能可能更有用的场景。
1. 性能报告易于理解
#性能指标是数字。阅读数字比阅读段落容易得多。例如,工程师可能需要 1 秒钟的时间才能将 1 到 5 的性能评级作为数字理解。而同样的工程师可能需要至少 1 分钟的时间才能阅读完整的 500 字反馈总结。
如果有许多数字,则很容易总结或可视化它们以快速理解。例如,您可以通过查看直方图、平均值、分位数等来快速理解数百万个数字。如果一个指标具有数千个数据点的历史记录,那么您可以轻松绘制时间线以读取其趋势。
另一方面,拥有 n 个 500 字的文本几乎可以保证需要 n 倍的时间来理解这些文本。分析数千个历史描述(每个描述都有 500 个字)将是一项艰巨的任务。
2. 性能歧义性小
#将性能作为一组数字的另一个优点是其歧义性小。当您希望动画每帧的性能为 20 毫秒或 50 fps 时,对数字的不同解释的空间很小。另一方面,要使用文字来描述相同的动画,有人可能会称其为好,而另一个人可能会抱怨它不好。同样,不同的词语或短语可能会被不同的人解读为不同的意思。您可能会将可以接受的帧率解释为 60 fps,而其他人则可能将其解释为 30 fps。
数字仍然可能存在噪声。例如,测得的每帧时间可能是该帧的真实计算时间,加上 CPU/GPU 在某些无关工作上花费的随机时间量(噪声)。因此,指标会波动。然而,数字的含义没有歧义。而且,还有严格的理论和测试工具来处理这种噪声。例如,您可以进行多次测量以估计随机变量的分布,或者您可以取多次测量的平均值以通过大数定律消除噪声。
3. 性能具有可比性和可转换性
#性能数字不仅具有明确的含义,而且还具有明确的比较性。例如,毫无疑问 5 大于 4。另一方面,判断优秀是否优于极好可能是主观的。同样,你能弄清楚史诗是否优于传奇吗?实际上,短语“大大超出预期”在某些人的解释中可能比“极好”更好。只有在将“大大超出预期”映射到 4 而将“极好”映射到 5 的定义之后,它才变得明确且具有可比性。
数字也可以使用公式和函数轻松转换。例如,60 fps 可以转换为每帧 16.67 毫秒。帧的渲染时间 x (毫秒) 可以转换为二进制指示符 isSmooth = [x <= 16] = (x <= 16 ? 1 :0)
。这种转换可以复合或链接,因此您可以使用单个测量获得各种各样的数量,而不会增加任何噪声或歧义。然后,转换后的数量可以用于进一步比较和理解。如果您处理的是自然语言,则这种转换几乎是不可能的。
4. 性能是公平的
#如果问题依赖于冗长的文字来发现,那么那些更冗长(更愿意聊天或写作)的人或那些更接近开发团队的人就会获得不公平的优势,他们拥有更大的带宽和更低的聊天或面对面会议的成本。
通过使用相同的指标来检测问题,无论用户离多远或多么沉默,我们都可以公平地对待所有问题。这反过来又使我们能够关注对影响更大的正确问题。
如何使性能更有用
#以下是此处讨论的 4 个要点,从略微不同的角度总结:
使性能指标易于理解。不要用大量的数字(或文字)淹没读者。如果有很多数字,则尝试将它们总结为更少数量的数字(例如,将许多数字总结为单个平均数)。只有当数字发生显著变化时才通知读者(例如,对峰值或倒退的自动警报)。
使性能指标尽可能明确。定义数字使用的单位。精确描述数字的测量方法。使数字易于复制。当有很多噪声时,尝试显示完整的分布,或者通过聚合许多噪声测量来尽可能消除噪声。
使性能比较变得容易。例如,提供时间线以将当前版本与旧版本进行比较。提供转换一个指标到另一个指标的方法和工具。例如,如果我们可以将内存增加和 fps 下降都转换为以美元计算的用户下降或收入损失数量,那么我们可以对它们进行比较并做出明智的权衡。
使性能指标监控尽可能广泛的人群,这样就不会有人被遗漏。
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。