blob: f9b76889e64b5b47f6126930a46e0dd1b18241ed [file] [log] [blame] [view]
# [FTP](../README.md)-027: You only pay for what you use
Field | Value
----------|--------------------------
Status | Accepted
Authors | abarth@google.com
Submitted | 2019-01-19
Reviewed | 2019-02-04
# Summary
This document proposes a design principle that we should apply during the FTP
review process:
> You only pay for what you use
Specifically, when adding functionality to FIDL, we should evaluate the costs
that adding that functionality imposes on people who use FIDL but do not use the
new functionality. We should then have a very high bar for accepting
functionality that imposes costs on people who do not use the functionality.
# Motivation
One of the most important aspects of FIDL is that Fuchsia uses FIDL pervasively
for interprocess communication and therefore for defining the [system
ABI](/docs/concepts/system/abi/system.md).
Many use cases for interprocess communication are performance-critical. When
people are evaluating technologies for these performance-critical use cases,
FIDL is competing against custom message formats and ad-hoc serialization and
deserialization routines.
Other uses cases for interprocess communication are flexibility-critical. When
people are evaluating technologies for these flexibility-critical use cases,
FIDL is competing against protobufs or a host of other networking-oriented
message formats.
In order to succeed at being used pervasively throughout Fuchsia, FIDL needs to
address both needs. Specifically, protocol designers working in FIDL need the
ability to make tradeoffs between performance and flexibility in order to meet
their needs.
Adopting the design principle of "you only pay for what you use" lets
performance-critical customers avoid paying for functionality that support
flexibility whereas its dual, "do pay for what you do use," lets FIDL serve
flexibility-critical customers.
# Design
This section describes the history of how we arrived at this design principle as
well as positive and negative examples.
## History
FIDL is an evolution of the
[Mojo](https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/)
interprocess communication system. At the time, Mojo was significantly more
flexible than FIDL, which worked well for flexibility-critical use cases.
However, customers with performance-critical use cases were unwilling to adopt
Mojo because the flexibility offered by the system did not meet their needs.
The original design for FIDL2 (the current version iteration of FIDL as of this
writing, circa 2017-03-01) picked a different point in the design space. In
order to win over performance-critical customers, FIDL2 is significantly less
flexible than Mojo, which lets FIDL2 be performance-competitive with custom
message formats and ad-hoc serialization and deserialization routines. Some
clients still demand ad-hoc serialization and deserialization routines, but
FIDL2 has succeeded in being used pervasively for message formats for
interprocess communication.
The original design for FIDL2 over-rotated towards performance and needed to be
improved to meet the needs of flexibility-critical customers. In order to be
successful, FIDL needs to add functionality that supports use cases for
flexibility without compromising on performance for customers that do not
require flexibility.
## Structs and tables
A positive example for "you only pay for what you use" is [FTP-007](ftp-007.md),
which introduced tables. Rather than replace structs (which have a fixed size
and layout, supporting performance-critical use cases), tables are a separate
data type which support flexibility-critical use cases. Protocol designers are
able to choose whether to pay for flexibility.
## Extensible unions
Another important example is FTP-015 (TODO(abarth): provide link), which
introduces extensible unions. This example illustrates that we should not
blindly apply the principle. In that design, there is a choice of whether to
introduce extensible unions as a separate concept or whether to replace all
non-extensible unions with extensible unions.
This choice boils down to making a value judgment weighing the performance cost
of imposing flexibility on all clients of union against the complexity cost of
having two largely overlapping constructs (e.g., imposing cognative load on
protocol designers to pick the right construct for their use case). In this
case, we analyzed the clients of unions and decided that the vast majority of
them value flexibility, which means imposing the costs of flexibility upon the
vast majority of union client does not cause them to pay for functionality they
do not use. For the handful of uses that did not value flexibility, we
consulted with the customers and agreed that the extra costs would not be
burdensome.
# Implementation strategy
One strategy for designing an interprocess communication system is figure out
the ideal balance of all concerns up front and then implement the system.
Unfortunately, the concerns involved in designing an interprocess communication
system are sufficiently complex that this strategy is beyond human ability.
Instead, we are pursuing a strategy by which we do as well as we can today and
then iteratively refine the design to better address the needs of our customers.
Broadly speaking, there are two strategies we can use to balance the concerns of
performance and flexibility: we can approach the ideal balance from either
overemphasizing performance or overemphasizing flexibility.
Another way to interpret this document is as proposing that we structure the
engineering program for FIDL to start by overemphasizing performance (as in the
original FIDL2 design) and then approach the idea balance between performance
and flexibility by adding flexibility while holding the line on performance.
In evaluating changes to FIDL, and as part of the FTP process, we expect this
principle to be weighed against other design considerations. When two principles
are at odds, there are a number of approaches appropriate to resolving ties:
evaluate the impact with potentially affected users, look at prior art (e.g.,
optimization work of Protobuf, or FlatBuffers design choices), think of who
needs to absorb the complexity (e.g., users, language designers, binding
authors), consider whether the design puts a limit on the theoretical max
performance (even if today's implementation falls short of that). Ultimately, we
will need to use our judgment about how best to balance these factors.
# Documentation and examples
This document proposes adding the "you only pay for what you use" principle to
the list of efficiency goals for FIDL.
# Backwards compatibility
This principle is backwards compatible with the current FIDL design and
engineering program.
# Performance
This principle values performance.
# Security
This principle could potentially have a negative impact on security because
satisfying the principle might result in a more complex system (e.g., that has
both structs and tables).
# Drawbacks, alternatives, and unknowns
One cost of this proposal is foreclosing design space that could be used to meet
flexibility-critical use cases at the expense of performance-critical use cases.
Another cost is adopting this design principle will cause the FIDL system to be
more complex than it would otherwise have been. For example, using tables
everywhere might be simpler than using structs in some places and tables in
other places. This added complexity is a burden both for the FIDL
implementation and for developers who use FIDL. To mitigate this drawback, we
should consider this complexity cost when applying the principle.
Another strategy for balancing the concerns of performance and flexibility would
be to approach the ideal balance by overemphasizing flexibility. The difficulty
with this approach is that human beings engineer systems by adding code rather
than removing code (e.g., similar to sculpting in clay rather than sculpting in
marble). It’s easier to add flexibility by adding code than it is to add
performance by adding code.
# Prior art and references
Many other languages have adopted the “you only pay for what you use” design
principle, including C++ [1] and Rust [2].
[1] B. Stroustrup. The Design and Evolution of C++. Addison Wesley, ISBN
0-201-54330-3. March 1994.
[2] J. Orendorff, J. Blandy. Programming Rust. O'Reilly Media, ISBN
9781491927274.
https://www.oreilly.com/library/view/programming-rust/9781491927274/ch01.html