RFC-0114:在 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;
}
InlinedValueEnvelope
和 OutOfLineWireEnvelope
均采用线上表示形式
有重叠的 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 引入了高效信封,它们构成了信封结构的基础 。