| RFC-0113:高效信封 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 此 FTP 提出了一种更紧凑的信封编码。 |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2021-06-21 |
| 审核日期(年-月-日) | 2021-07-21 |
“将信封变成明信片”
摘要
此 RFC 提出了一种更紧凑的 FIDL 编码1。
设计初衷
信封是可扩展、可演变的数据结构(表和可扩展的联合)的基础。 更紧凑高效的信封线格式使这些可扩展结构能够用于更多注重性能和线大小的场景。
设计
提议的信封格式可描述为以下 C 结构:
struct Envelope {
uint32_t byte_size;
uint32_t handle_count;
};
与现有信封格式相比:
- 字节大小字段保持不变(32 位)。
- 该大小包括可能以递归方式编码的任何子对象的大小。
- 例如,
vector<string>的大小包括外部向量的内部字符串子对象的大小。 - 这与当前信封实现的大小字段的现有行为相匹配。
- 句柄数量字段保持不变(32 位)。
- handle_count 包括所有递归子对象的句柄数。
- 已舍弃存在/缺失字段。
- 如果 size 或 handle_count 字段中的值为非零值,则表示存在。
- 如果大小和句柄数字段均为零,则表示不存在。
- 我们将这种情况称为零信封。
- 零包络线相当于
FIDL_ALLOC_ABSENT。
- 字节大小字段的验证
- 必须验证字节大小字段是否为 8 的倍数。
解码器可以使用指向信封数据的指针覆盖信封,前提是它们知道信封内容的静态类型(架构)。如需了解在内容类型未知的情况下如何处理信封,请参阅未知数据部分中的建议。
用于编码/解码形式的 C/C++ 结构
信封的编码或解码形式可以描述为 C 联合:
typedef union {
struct {
uint32_t byte_size;
uint32_t handle_count;
} encoded;
void* data;
} fidl_envelope_t;
static_assert(sizeof(fidl_envelope_t) == sizeof(void*));
未知数据
当接收器(验证器和解码器)在可演变的数据结构中使用时,可能不知道信封的类型。如果接收者不知道类型,则可以对信封进行最少的解析并跳过。
- 信封的大小决定了要跳过的带外数据量。
- 如果信封的句柄数量不为零,验证器必须存储或关闭每个句柄。
- 如果解码器希望就地解码,则可能会使用指向信封内容的指针覆盖未知信封。
- 如果解码器确实使用指针覆盖了信封,它将丢失信封中的大小和句柄计数信息。 绑定可能会提供一种机制,让解码器在覆盖信封之前保存大小和句柄数量信息;本 RFC 不会就此类机制的运作方式发表意见。
实施策略
此 RFC 是一项重大线格式变更。
我们将进行复杂的线格式迁移,以切换到高效的信封。此线格式变更将与其他迁移相结合,以降低每个功能的迁移成本。
向后兼容性
提议的线格式更改与 API(来源)兼容。任何手动编写的 FIDL 代码都需要更新,以处理新的有线格式。
传输格式更改与 ABI 不兼容。
性能
在 CL 中运行了性能评估,该 CL 可高效实现信封功能。在此测试中,输入是一个设置了所有字段的表格。其他输入也产生了类似的结果。
以下时间以纳秒为单位。没有高效信封的时间在箭头之前,有高效信封的时间在箭头之后。
| # 字段 | 编码 | Decode |
|---|---|---|
| 16 | 64 -> 40 | 176 -> 146 |
| 64 | 165 -> 121 | 321 -> 221 |
| 256 | 567 -> 368 | 923 -> 527 |
| 1024 | 2139 -> 1429 | 3284 -> 1636 |
根据输入内容,使用高效信封似乎快了 1.1-2 倍
工效学设计
- 更高效的可扩展数据结构使其能够用于更多注重效率的情境,因此用户无需过于担心其性能,并且可以获得可扩展性的好处,而以前他们需要使用不可扩展的结构。
- 我们甚至可能希望建议默认情况下应将表用于 FIDL 数据结构,而应将结构保留用于高性能上下文。
- 可扩展的联合 (RFC-0061) 已经尝试移除静态联合。
文档
- 需要更新线上传输格式文档。
- 更新文档时,应将信封作为第一类概念进行说明:这样一来,读者在遇到可选性和可扩展数据结构的线格式时,可以更好地进行认知组块化。
- 我们应更新 FIDL 样式指南,以建议何时应使用可扩展类型。
安全
此 RFC 不应有任何安全隐患。
一个次要的安全优势是,此 RFC 移除了旧格式中大小和指针中重复的信息。
之前,可能会收到大小/句柄不为零且 FIDL_ALLOC_ABSENT 的信封,或者大小/句柄为零且 FIDL_ALLOC_PRESENT 的信封。这需要额外的验证检查,但现在不再需要了。
仅凭数据无法确定信封是采用有线形式还是解码形式。这不是问题,因为在实践中,绑定中始终存在单独的账簿来跟踪消息是处于序列化形式还是解码形式。
隐私权
此 RFC 不应有任何隐私权影响。
测试
- 由于此 RFC 正在更改信封的线格式,我们认为现有的 FIDL 测试套件(尤其是兼容性测试)将充分测试使用信封的所有场景。
- 如果我们同意以软过渡方式实现线格式更改(请参阅实施策略部分),我们将添加测试,以便对等方协商并可能切换到新的线格式。
缺点、替代方案和未知因素
如果我们认为此提案中的效率提升不值得付出实现成本,则可以保留现有的有线格式。
之前拒绝了 RFC,现在批准的理由
此 RFC 之前被拒绝,以下是拒绝理由(此处为逐字复制),之后又重新提交以供审核:
2019 年 2 月 21 日,此 RFC 最初被接受。FIDL 团队在 2019 年的大部分时间里都在努力稳定线格式,最终在第 3 季度和第 4 季度开展了全员参与的努力。迁移已于 2019 年 12 月 1日完成。
此次稳定化工作涉及多项更改:
不过,随着工作的推进,12 月 1日的截止日期临近,FIDL 团队决定推迟实现高效信封变更,而是选择将这项工作推迟到 2020 年。与其他属于稳定化工作的更改不同,高效信封只是节省了内存大小,而且节省的内存非常小,尤其是与其他 FIDL 有线格式方面(例如表格的密集格式)相比。延期是一种项目风险降低计算,通过缩小范围,按时完成所有工作的几率得到了提高。FIDL 团队的工作安排也是如此。
现在,延期已经过去近 18 个月,高效信封早已被遗忘。2020 年开展的大量性能工作表明,此变更不会产生重大影响。
是时候面对现实了,这不会发生。已拒绝。
为何现在需要重新批准?
FIDL 团队目前正计划将多项线格式更改批处理在一起,并一次性完成所有更改的迁移。这意味着,我们可以以较低的成本(与其他迁移共享成本)添加对高效信封的支持。
此外,现在还有了因高效信封而带来的性能提升的具体数据,而且提升幅度非常大。
鉴于上述因素,现在是重新提出此 RFC 并实现它的好时机。
在先技术和参考资料
此 RFC 是 rfc-0026 的简化版本,后者因未获得足够共识而被拒绝。