RFC-0027:只需为实际用量付费

RFC-0027:您只需按实际用量付费
状态已接受
区域
  • FIDL
说明

向 FIDL 添加功能时,我们应评估添加该功能对使用 FIDL 但不使用新功能的人员造成的成本。因此,对于会给不使用相应功能的人带来成本的功能,我们应设置非常高的接受门槛。

作者
提交日期(年-月-日)2019-01-19
审核日期(年-月-日)2019-02-04

摘要

本文档提出了一项设计原则,我们应在 RFC 审核流程中应用该原则:

您只需为实际用量付费

具体而言,在向 FIDL 添加功能时,我们应评估添加该功能对使用 FIDL 但不使用新功能的人员造成的成本。因此,对于会给不使用该功能的人带来成本的功能,我们应设置非常高的接受门槛。

设计初衷

FIDL 最重要的一个方面是,Fuchsia 广泛使用 FIDL 进行进程间通信,因此也使用 FIDL 来定义系统 ABI

许多进程间通信用例对性能要求很高。当人们评估这些对性能要求极高的用例的技术时,FIDL 会与自定义消息格式以及临时序列化和反序列化例程竞争。

进程间通信的其他用例对灵活性要求很高。当人们评估这些对灵活性要求极高的使用场景的技术时,FIDL 会与 protobuf 或许多其他面向网络的讯息格式竞争。

为了在整个 Fuchsia 中得到广泛使用,FIDL 需要同时满足这两个需求。具体而言,使用 FIDL 的协议设计者需要能够在性能和灵活性之间做出权衡,以满足自己的需求。

采用“仅为实际用量付费”的设计原则,可让对性能要求较高的客户避免为支持灵活性的功能付费,而其对偶原则“为实际用量付费”则可让对灵活性要求较高的客户使用 FIDL。

设计

本部分介绍了我们如何得出这一设计原则,并提供了正面和负面示例。

历史记录

FIDL 是 Mojo 进程间通信系统的升级版。当时,Mojo 比 FIDL 灵活得多,非常适合对灵活性要求较高的使用情形。不过,对于性能至关重要的用例,客户不愿意采用 Mojo,因为该系统提供的灵活性无法满足他们的需求。

FIDL2(截至撰写本文时的当前 FIDL 版本迭代,大约在 2017 年 3 月 1 日)的原始设计在设计空间中选择了不同的点。为了赢得对性能要求极高的客户,FIDL2 的灵活性远不如 Mojo,这使得 FIDL2 在性能方面能够与自定义消息格式以及临时序列化和反序列化例程相媲美。虽然有些客户仍然需要临时序列化和反序列化例程,但 FIDL2 已成功广泛用于进程间通信的消息格式。

FIDL2 的原始设计过度侧重于性能,需要改进以满足对灵活性要求极高的客户的需求。为了取得成功,FIDL 需要添加支持灵活性的使用情形的功能,同时不会牺牲不需要灵活性的客户的性能。

结构体和表格

“您只需要按照实际用量付费”的一个正面示例是引入了表格的 RFC-0047。表不是替换结构体(结构体具有固定的大小和布局,支持对性能要求高的使用情形),而是一种单独的数据类型,支持对灵活性要求高的使用情形。协议设计者可以选择是否为这种灵活性付费。

可扩展的联合

另一个重要示例是 RFC-0061,它引入了可扩展的联合。此示例说明,我们不应盲目应用该原则。在该设计中,可以选择是将可扩展的联合作为单独的概念引入,还是用可扩展的联合替换所有不可扩展的联合。

此选择归结为做出价值判断,即权衡对联合的所有客户端施加灵活性所带来的性能成本,与拥有两个在很大程度上重叠的构造所带来的复杂性成本(例如,对协议设计者施加认知负荷,让他们为自己的使用情形选择正确的构造)。在这种情况下,我们分析了工会的客户,并确定绝大多数客户都重视灵活性,这意味着将灵活性的成本转嫁给绝大多数工会客户不会导致他们为不使用的功能付费。对于少数不重视灵活性的用途,我们与客户进行了咨询,并一致认为额外费用不会造成负担。

实施策略

设计进程间通信系统的一种策略是,预先确定所有相关问题的理想平衡点,然后实现该系统。遗憾的是,设计进程间通信系统涉及的考虑因素非常复杂,这种策略超出了人类的能力范围。相反,我们正在推行一项策略,即先尽我们所能做好当前的工作,然后迭代式地改进设计,以更好地满足客户的需求。

从广义上讲,我们可以使用两种策略来平衡性能和灵活性方面的考虑因素:我们可以从过分强调性能或过分强调灵活性的角度来达到理想的平衡。

对本文档的另一种解读是,建议我们构建 FIDL 工程计划,首先过分强调性能(如原始 FIDL2 设计),然后通过在保持性能底线的同时增加灵活性,来达到性能和灵活性之间的理想平衡。

在评估 FIDL 更改时,作为 RFC 流程的一部分,我们希望将此原则与其他设计考虑因素进行权衡。如果两个原则相互冲突,可以采取多种方法来解决冲突:评估对可能受影响的用户的冲击、查看现有技术(例如 Protobuf 的优化工作或 FlatBuffers 设计选择)、考虑谁需要承担复杂性(例如用户、语言设计者、绑定作者)、考虑设计是否限制了理论上的最大性能(即使今天的实现达不到该水平)。最终,我们需要自行判断如何最好地平衡这些因素。

文档和示例

本文档建议将“按用量付费”原则添加到 FIDL 的效率目标列表中。

向后兼容性

此原则向后兼容当前的 FIDL 设计和工程计划。

性能

此原则重视性能。

安全

此原则可能会对安全性产生负面影响,因为满足此原则可能会导致系统更加复杂(例如,同时包含结构和表)。

缺点、替代方案和未知因素

此提案的一个代价是,它会限制可用于满足灵活性关键用例的设计空间,但会牺牲性能关键用例。

采用此设计原则的另一个代价是,FIDL 系统会比原本更加复杂。例如,在所有位置都使用表格可能比在某些位置使用结构而在其他位置使用表格更简单。这种额外的复杂性会给 FIDL 实现和使用 FIDL 的开发者带来负担。为了缓解这一缺点,我们在应用该原则时应考虑这种复杂性成本。

另一种平衡性能和灵活性的策略是,通过过分强调灵活性来接近理想的平衡点。这种方法的难点在于,人类是通过添加代码(例如,类似于用黏土雕刻,而不是用大理石雕刻)来设计系统的。添加代码来提高灵活性比添加代码来提高性能更容易。

在先技术和参考资料

许多其他语言也采用了“按需付费”的设计原则,包括 C++1 和 Rust2


  1. B. Stroustrup。The Design and Evolution of C++。Addison Wesley,ISBN 0-201-54330-3。1994 年 3 月。 

  2. J. Orendorff, J. Blandy。Programming Rust。O'Reilly Media,ISBN 9781491927274。https://www.oreilly.com/library/view/programming-rust/9781491927274/ch01.html