# 性能

性能是编辑器应用的关键特性，区块编辑器也不例外。

## 指标

为确保区块编辑器在版本迭代和开发过程中保持高性能，我们通过[性能基准测试任务](#the-performance-benchmark-job)监控若干关键指标。

部分核心重要指标包括：

- **加载时间：** 加载编辑器页面所需时长。包含服务器响应时间、首次绘制时间、首次内容绘制时间、DOM内容加载完成时间、页面完全加载时间以及首个区块渲染时间（文章与站点场景均涵盖）。
- **输入响应时间：** 在编辑器中输入时浏览器的响应时长。
- **区块选择时间：** 用户选择区块后浏览器的响应时长（插入区块等同于选择区块，监控选择时间即可覆盖这两项指标）。

## 关键性能决策与解决方案

**数据模块异步模式**

WordPress 包和区块编辑器的数据模块基于 Redux 构建。这意味着状态被全局保存，每当状态发生变化时，依赖该状态的组件（UI）可能会更新。

随着渲染组件数量的增加（例如在长篇文章中），由于全局状态充当所有组件的事件分发器，性能会受到影响。这是 Redux 应用中的常见陷阱，Gutenberg 通过数据模块的异步模式解决了这个问题。

异步模式的核心思想是：您可以决定是同步还是异步地刷新/重新渲染 React 组件树的一部分。

在此上下文中，异步渲染意味着：如果全局状态中触发了变更，订阅者（组件）不会被同步调用；相反，我们会等待浏览器空闲时再执行对 React 树的更新。

基于 **编辑特定区块时，对该区块的更新很少影响内容其他部分** 这一理念，区块编辑器画布仅以同步模式渲染选中的区块，所有其余区块均采用异步渲染。这确保了随着文章内容增长，编辑器仍能保持响应性。

## 性能基准测试任务

我们提供了一个工具，用于比较多个分支/标签/提交之间的性能。你可以像这样在本地运行它：`./bin/plugin/cli.js perf [branches]`，例如：

```
./bin/plugin/cli.js perf trunk v8.1.0 v8.0.0
```

为了获得最准确的结果，在运行测试时使用完全相同的测试版本和环境（主题等）非常重要，各分支之间唯一需要不同的就是 Gutenberg 插件版本（或用于构建插件的分支）。

为了实现这一点，该命令首先准备以下文件夹结构：

    │
    ├── tests/packages/e2e-tests/specs/performance/*
    |   要运行的实际性能测试
    │
    ├── tests/test/emptytheme
    |   用于测试环境的主题。（站点编辑器）
    │
    │── envs/branch1/.wp-env.json
    │   branch1 的 wp-env 配置文件（除了插件文件夹外，与其他所有分支类似）。
    │── envs/branch1/plugin
    │   branch1 的 Gutenberg 插件的构建克隆（git checkout branch1）
    │
    └── envs/branchX
        perf-envs/branch1 的结构会为所有其他分支复制。

一旦上述目录准备就绪，性能命令会遍历性能测试套件（文章编辑器和站点编辑器）并执行以下操作：

1.  为 `branch1` 启动环境
2.  运行当前套件的性能测试
3.  为 `branch1` 停止环境
4.  对所有其他分支重复前 3 个步骤
5.  计算当前套件所有性能指标的中位数。

所有测试套件执行完毕后，会打印一份摘要报告。

## 使用 CodeVitals 追踪性能表现。

每次提交的性能结果都会推送到 codevitals，并可在 [Gutenberg 仪表板](https://www.codevitals.run/project/gutenberg) 上查看。图表使我们能够追踪特定指标随时间的变化趋势。

因此，确保计算的指标稳定至关重要。这意味着，如果在相同代码和环境下运行同一测试两次，你将获得相近的结果。

我们的性能任务运行在 GitHub CI 上，这意味着我们不能信任两次类似任务运行之间所得数据的一致性。例如，GitHub CI 可能随时间为我们分配不同的 CPU 和内存资源。为了缓解此问题，每次在主干分支上运行性能任务时，我们会将当前提交的性能与固定的参考提交哈希值进行比较，这使我们能够一致地追踪当前提交与参考提交之间的相对差异，而不受环境变化的影响。

### 更新基准提交

Gutenberg 仅支持两个 WordPress 版本，这从两方面影响性能测试任务：

 - 当 Gutenberg 支持的最低版本变更时，用于运行性能测试任务的基准 WordPress 版本需要更新。为此，我们依赖插件 `readme.txt` 文件中的 `Tested up to` 标志。因此，每次该标志变更时，性能测试任务使用的版本也会随之改变。

 - 更新性能测试任务使用的 WordPress 版本意味着，用于性能测试稳定性的基准提交很可能与使用的 WordPress 版本不兼容。因此，每次 `readme.txt` 中的 `Tested up to` 标志更新时，我们也必须更新 `.github/workflows/performance.yml` 中使用的基准提交。

选择的新基准提交哈希值需满足以下要求：

 - 与 "Tested up to" 标志中使用的新 WordPress 版本兼容。
 - 已在 "codevitals.run" 上追踪所有现有指标。

当发布包含最低 WordPress 版本要求变更的插件更新时，对于任何失去支持的分支，Core SVN 中的端到端测试 GitHub Action 工作流都需要更新。否则，发布后该分支上该工作流的首次运行将失败。

可以通过在测试矩阵中添加 `gutenberg-version` 输入来固定工作流中使用的插件版本。[Core-59221](https://core.trac.wordpress.org/changeset/59221) 是针对 6.4 分支进行此更改的示例。

**注意：** 始终使用包含错误修复的最终版本（例如 `x.y.2` 或 `x.y.3`）。如果最终版本尚未确定，请创建一个 [Trac 工单](https://core.trac.wordpress.org/ticket/62488) 以免遗忘。

**选择提交的一个简单方法是挑选主干上一个非常近期且性能测试任务通过的提交。**

## 深入探索

-   [通往高性能编辑器的旅程](https://riad.blog/2020/02/14/a-journey-towards-a-performant-web-editor/)