RFC-0113:高效的信封

RFC-0113:高效封装
状态已接受
区域
  • FIDL
说明

此 FTP 为信封提出了更紧凑的编码。

Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-06-21
审核日期(年-月-日)2021-07-21

“将信封改造成明信片”

摘要

此 RFC 为 FIDL1 提出了更紧凑的编码。

设计初衷

封装容器是可扩展、可演化的数据结构(表和可扩展联合体)的基础。封装容器的线格格式更紧凑、更高效,这使得这些可扩展结构可在性能和线格大小至关重要的更多情境中使用。

设计

提议的信封格式可以描述为以下 C 结构体:

struct Envelope {
    uint32_t byte_size;
    uint32_t handle_count;
};

现有信封格式相比:

  • 字节大小字段保持不变(32 位)。
    • 大小包括可能递归编码的任何子对象的大小。
    • 例如,vector<string> 的大小包括外部矢量内部字符串子对象的大小。
    • 这与当前封装容器实现的 size 字段的现有行为一致。
  • 句柄计数字段保持不变(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 中运行了性能评估,以对高效封装容器实现进行原型设计。在本测试中,输入是设置了所有字段的表。其他输入也产生了类似的结果。

以下时间均以纳秒为单位。没有高效封装的时间在箭头前面,使用高效封装的时间在箭头后面。

# 字段 编码 解码
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 最初获得接受。在 2019 年的大部分时间里,FIDL 团队致力于稳定线程格式,最终在第 3 季度和第 4 季度期间全力以赴。迁移已于 2019 年 12 月 1完成。

稳定性工作涵盖了多项变更:

不过,随着工作开展,12 月 1 日的截止日期迫在眉睫,FIDL 团队决定推迟实现高效信封更改,而将此工作推迟到 2020 年。与稳定性工作中涉及的其他更改不同,高效封装容器只是节省了内存大小,而且节省的空间非常小,尤其是与 FIDL 线格式(例如表的紧密格式)的其他方面相比。推迟是项目风险降低计算的结果,通过缩减范围,可以提高按时完成所有工作的几率。FIDL 团队的工作安排也是如此。

现在,距离推迟发布已经将近 18 个月,高效信封早已被人遗忘。2020 年开展的大量效果提升工作表明,此次变更不会产生重大影响。

是时候面对现实了,这种情况不会发生。已拒绝。

为何现在重新审批?

FIDL 团队目前计划将多项线格格式更改打包在一起,并一次性进行迁移。这意味着,我们有机会以更低的成本(费用与其他迁移共享)添加对高效封装容器的支持。

此外,现在可以通过具体的数字来衡量高效封装带来的性能提升,而且提升幅度非常显著。

鉴于这些因素,现在是时候重新启用此 RFC 并加以实现了。

在先技术和参考文档

此 RFC 是 rfc-0026 的精简版,由于整个 RFC 未达成足够的共识,因此该 RFC 被拒绝。


  1. 此 RFC 基于 rfc-0026,但包含线下信封提案。内嵌、所有封装容器以及将字符串/向量计数移出行都已移除。