RFC-0027:只需为实际使用的资源付费 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 向 FIDL 添加功能时,我们应评估向使用 FIDL 但不使用新功能的用户添加该功能所带来的成本。因此,我们应对接受会给不使用该功能的用户带来费用的功能设定非常高的门槛。 |
作者 | |
提交日期(年-月-日) | 2019-01-19 |
审核日期(年-月-日) | 2019-02-04 |
摘要
本文档提出了我们应在 RFC 审核流程中应用的设计原则:
只需为实际用量付费
具体而言,在向 FIDL 添加功能时,我们应评估向 FIDL 添加该功能对使用 FIDL 但不使用新功能的用户造成的影响。因此,我们应该对会给不使用该功能的用户带来成本的功能设定非常高的接受标准。
设计初衷
FIDL 最重要的一点是,Fuchsia 广泛使用 FIDL 进行进程间通信,因此也用于定义系统 ABI。
许多进程间通信用例都对性能至关重要。在评估适用于这些对性能至关重要的用例的技术时,FIDL 与自定义消息格式以及临时序列化和反序列化例程展开竞争。
进程间通信的其他用例对灵活性至关重要。当人们评估这些对灵活性至关重要的用例所需的技术时,FIDL 会与 protobuf 或一系列其他面向网络的消息格式展开竞争。
为了在 Fuchsia 中广泛使用,FIDL 需要同时满足这两种需求。具体而言,使用 FIDL 的协议设计人员需要能够在性能和灵活性之间做出权衡,以满足他们的需求。
采用“只需为实际使用的功能付费”的设计原则,可让注重性能的客户避免为支持灵活性的功能付费;而采用“只需为实际使用的功能付费”的设计原则,则可让 FIDL 为注重灵活性的客户提供服务。
设计
本部分介绍了我们是如何得出这一设计原则的,以及正面和负面示例。
历史记录
FIDL 是 Mojo 进程间通信系统的演变。当时,Mojo 比 FIDL 灵活得多,非常适合灵活性至关重要的用例。但是,对于对性能至关重要的用例,客户不愿采用 Mojo,因为该系统提供的灵活性无法满足他们的需求。
FIDL2(本文撰写之时,即大约 2017 年 3 月 1 日,FIDL 的当前版本迭代)的原始设计选择了设计空间中的另一个点。为了赢得对性能要求苛刻的客户,FIDL2 的灵活性远不如 Mojo,这使得 FIDL2 在性能方面与自定义消息格式和临时序列化和反序列化例程具有竞争力。某些客户端仍需要使用临时序列化和反序列化例程,但 FIDL2 已成功广泛用于进程间通信的消息格式。
FIDL2 的原始设计过于侧重于性能,需要改进才能满足对灵活性至关重要的客户的需求。为了取得成功,FIDL 需要添加支持灵活用例的功能,同时又不会影响不要求灵活性的客户的性能。
结构体和表
“您只需按照实际用量付费”的正例是 RFC-0047,其中引入了表格。表是一种单独的数据类型,用于支持对灵活性至关重要的用例,而不是替换结构体(结构体具有固定的大小和布局,支持对性能至关重要的用例)。协议设计者可以选择是否为这种灵活性付费。
可扩展的联合
另一个重要的示例是 RFC-0061,它引入了可扩展的联合体。此示例说明了我们不应盲目地应用该原则。在该设计中,您可以选择是将可扩展联合体作为一个单独的概念引入,还是将所有不可扩展的联合体替换为可扩展的联合体。
归根结底,此选择需要做出价值判断,权衡强制为所有联合客户提供灵活性的性能开销与拥有两个很大程度上重叠的结构的复杂性开销(例如,强制协议设计师为其用例选择正确的结构会给他们带来认知负担)。在这种情况下,我们分析了联盟的客户,并确定绝大多数客户都注重灵活性,这意味着,向绝大多数联盟客户收取灵活性费用不会导致他们为自己不使用的功能付费。对于少数不看重灵活性的用例,我们与客户进行了协商,并达成一致,认为额外费用不会成为负担。
实施策略
设计进程间通信系统的一种策略是,先确定所有方面之间的理想平衡,然后再实现该系统。遗憾的是,设计进程间通信系统涉及的问题非常复杂,因此这种策略超出了人类的能力范围。我们采用的策略是,先尽力做好当前的设计,然后迭代优化设计,以更好地满足客户的需求。
一般来说,我们可以采用两种策略来平衡性能和灵活性方面的问题:我们可以通过过度强调性能或过度强调灵活性来实现理想的平衡。
另一种解读此文档的方式是,建议我们为 FIDL 构建工程计划,首先要过度强调性能(如原始 FIDL2 设计),然后通过增加灵活性并保持性能不变,在性能和灵活性之间实现理想的平衡。
在评估对 FIDL 的更改时,我们希望在 RFC 流程的过程中,将此原则与其他设计注意事项进行权衡。当两项原则相互冲突时,有许多方法可以解决这种情况:评估对可能受影响的用户的影响、查看先前技术(例如 Protobuf 的优化工作或 FlatBuffers 设计选项),考虑需要吸收复杂性的人员(例如用户、语言设计人员、绑定作者),考虑设计是否会限制理论上的最大性能(即使当前的实现不符合这一点)。最终,我们需要根据自己的判断来决定如何最好地平衡这些因素。
文档和示例
本文档建议将“只需为所用付费”原则添加到 FIDL 的效率目标列表中。
向后兼容性
此原则与当前的 FIDL 设计和工程计划向后兼容。
性能
此原则重视性能。
安全
此原则可能会对安全性产生负面影响,因为满足此原则可能会导致系统更复杂(例如,同时包含结构体和表)。
缺点、替代方案和未知情况
此方案的一个代价是,它会排除可用于满足对灵活性要求极高的用例的设计空间,而这会降低对性能要求极高的用例的支持。
另一个代价是,采用此设计原则会导致 FIDL 系统比原本更复杂。例如,在所有位置使用表格可能比在某些位置使用结构体,在其他位置使用表格更简单。这种额外的复杂性对 FIDL 实现和使用 FIDL 的开发者来说都是负担。为了缓解这一缺点,我们应在应用该原则时考虑这种复杂性开销。
平衡性能和灵活性问题的另一种策略是,通过过度强调灵活性来实现理想的平衡。这种方法的难点在于,人类通过添加代码(而非移除代码)来构建系统(例如,类似于用粘土雕塑,而不是用大理石雕塑)。通过添加代码来提高灵活性要比通过添加代码来提高性能更容易。
在先技术和参考文档
许多其他语言也采用了“只需为实际用量付费”的设计原则,包括 C++1 和 Rust2。