RFC-0114:将较小的值内联到 FIDL 信封中

RFC-0114:在 FIDL 信封中内嵌较小的值
状态已接受
领域
  • FIDL
说明

此 RFC 提议对 FIDL 传输格式进行更改,将大小不超过 4 个字节的值内嵌到信封正文中。

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

摘要

此 RFC 提议对 FIDL 传输格式进行更改,将值内联 <= 4 个字节的 放入信封正文中

设计初衷

此变更的目的是提高 FIDL 表的性能, 并集(即目前使用信封的布局)。

FIDL 联合和表对行外对象使用共享表示法 称为“信封”外行指针是已知的开销来源 用于编码和解码。小物体可以内嵌在信封内 因此无需额外的开销。

此外,在某些情况下,还可以减少分配。改为 为对象分配外行位置并从 则对象可以直接存储在信封中。

设计

此 RFC 设计假设已获得批准, RFC-0113,引入了高效的信封。

以下类型将使用新的内嵌值格式:

  • bool
  • float32
  • uint8、uint16、uint32
  • int8、int16、int32
  • 布局为 uint8、uint16、uint32、int8、int16、int32 的枚举
  • 采用 uint8、uint16、uint32、int8、int16、int32 布局的位
  • 句柄、client_end、server_end
  • 结构体大小 <= 4 个字节
  • 数组大小 <= 4 个字节

如果日后添加了大小小于 4 个字节的新类型值, 除非另有说明,否则它们也会使用内联值格式。

新格式可以通过 C 结构体表示法进行描述:

// An envelope corresponds to a union value or an entry in a table.
struct Envelope {
    union {
        // Inlined values have the same envelope structure for both wire and
        // decoded formats.
        InlinedValueEnvelope inlined_value_envelope;

        // Out-of-line values have a different structure on the wire and in
        // decoded format.
        union OutOfLineEnvelope {
            // Wire representation.
            OutOfLineWireEnvelope out_of_line_wire_envelope;
            // Decoded representation.
            void* decoded_data;
        };
    };
};
struct InlinedValueEnvelope {
    // A <= 4-byte value stored little-endian and 0-padded up to 4-bytes.
    uint8_t value[4];
    // Number of handles within the envelope.
    uint16_t num_handles;
    // Bit 0 of flags is 1 to indicate the inline representation is used and
    // the envelope is present.
    uint16_t flags;
};
struct OutOfLineWireEnvelope {
    // Number of bytes recursively within the envelope.
    uint32_t num_bytes;
    // Number of handles recursively within the envelope.
    uint16_t num_handles;
    // Bit 0 of flags is 0 to indicate the out-of-line representation is used.
    uint16_t flags;
}

InlinedValueEnvelopeOutOfLineWireEnvelope 均采用线上表示形式 有重叠的 flags 字段。flags 中的 LSB 指示 是否使用内联形式:1 表示内联,0 表示外联。全部 未使用的标记位必须为 0

FIDL 中只有一种数据规范表示形式。 当前值必须内嵌且大小不超过 4 个字节,且值大于 4 个字节必须使用外行表示法。收到不正确的值 必须触发解码错误。 缺失的信封继续使用零信封表示法,这意味着 始终由行外表示法表示。

实现

此更改需要进行复杂的迁移。不过,这种迁移方式 与其他传输格式迁移相结合,从而大大降低 做法。

性能

当字段内嵌时,LLPP 中的编码时间会明显缩短 (CL):

对所有字段进行编码的时间(以纳秒为单位):

# 个字段 之前 之后
1 178 纳秒 147 纳秒
16 720 纳秒 325 纳秒
256 9396 纳秒 2909 纳秒

此图表显示了编码时间与表中字段数量的关系。 表中的所有字段均已设置。

未测量解码时间,但预计解码时间会有明显 而解码算法遵循一系列类似的步骤, 编码。

此外,在某些情况下,绑定或许能够 以优化小值,从而进一步提高性能。

工效学设计

此 RFC 允许绑定以避免分配较小的值,但不允许 要求他们必须这样做。如果绑定发生变化, 与处理这些类型的 API 其他需要分配的类型这种不一致可能会导致 必须小心,避免发生这种情况。

向后兼容性

此更改所需的迁移会破坏 ABI 兼容性。

不过,这项更改生效后,便不会对 ABI 兼容性产生任何影响 更改类型。所有小于等于 4 字节的类型都不能保证 ABI 此变更前后的类型变更的兼容性。

此变更可能会破坏源代码兼容性。没有源代码兼容性中断问题 RFC 要求进行更改,但绑定可以选择 兼容性破坏性更改(如果这些更改可以提高绑定性能) 或其他原因。

安全注意事项

这对安全性没有任何影响。

隐私注意事项

这对隐私权没有任何影响。

测试

系统将使用多种策略来测试更改:

  • 每个绑定中的自定义单元测试。
  • GIDL 一致性套件。
  • FIDL 兼容性测试。

文档

线上传输格式文档需要更新。

需要在 API 评分准则中记录性能权衡, 字段大小决策。

缺点、替代方案和未知问题

缺点

该方案的主要缺点是复杂性增加。现在,您可以 值的两种表示法:内联和外联(取决于类型) 令人惊讶的是,在进行切换时, 行为

替代方案:8 字节内嵌值

此 RFC 建议了不超过 4 个字节的内嵌值。 其原因在于, 8 字节值 - 至少与 efficiency 信封。

这样做的原因是绑定必须支持未知的信封。时间 收到未知的信封,则没有已知的类型信息。因此, 但不知道它是否指向了行外对象, 改变解码器的行为。因此 值本身中的信息,指示其是否在 内嵌或外排格式。

如果信封大小为 8 个字节,而内嵌的值为 8 个字节,则 。

因此,8 字节内联值与高效的 信封。需要做出选择,或者不采用高效信封 或缩减可内嵌值的大小。此 RFC 规范使得后者 因为这个方向似乎最有可能带来 性能的提升。

先验技术和参考资料

RFC-0113 引入了高效信封,它们构成了信封结构的基础 。