measure-tape
A measure tape simplifies maximizing the number of elements which can be batched
at once over a FIDL channel communication. More details on this topic are
provided in the guide max out pagination.
A measure tape lets you measure the size which FIDL values will take on the
wire, both in terms of number of bytes and number of handles. The
measure-tape
tool automatically generates code to create a measure tape for a
specific target type.
For instance, Scenic has an enqueue method which takes a vector of commands.
With this tool, we can generate a measure tape, i.e. code to measure each
command, which the Scenic client can leverage to batch commands appropriately,
and maximize throughput.
Build integration
To add a measure tape to your project, use the measure_tape
template:
measure_tape("measure_tape_for_targettype") {
target_binding = "hlcpp"
target_type = "fuchsia.your.library/TargetType"
fidls = [ ":fuchsia.your.library" ]
}
This template must be imported with
import("//tools/fidl/measure-tape/measure_tape.gni")
.
-
target_binding
key indicates what bindings to generate.
Valid values are currently "hlcpp" and "rust".
-
target_type
key indicates the FIDL target type for which to generate a
measure tape. It must be provided in its fully qualified form, e.g.
fuchsia.ui.scenic/Command
or fuchsia.mem/Buffer
-
fidls
key must list all FIDL libraries transitively reachable through the
target type. For instance, the fuchsia.ui.scenic/Command
requires
:fuchsia.images
, :fuchsia.ui.gfx
, :fuchsia.ui.input
,
:fuchsia.ui.scenic
, :fuchsia.ui.views
Using a measure tape
When constructing batches, use the measure tape to determine the size of
individual elements, and aggregate this size along with the batch being
constructed for transmission.
The following is a simplified example taking many Element
and
sending batches of vector<Element>
over a hypothetical SendNext
FIDL method.
The example assumes that Element
contains no handles. If your data contains
handles, be sure to also aggregate the handle count.
func sendInBatches(elements []Element, over YourFavoriteFidlBinding) {
var (
batchSize = baseBatchSize
batch []Element
)
for _, element := range elements {
size := Measure(element)
if zxMaxChannelBytes < batchSize+size {
over.SendNext(batch)
batch = nil
batchSize = baseBatchSize
}
batch = append(batch, element)
batchSize += size
}
if len(batch) != 0 {
over.SendNext(batch)
}
}
// sizeof(fidl_message_header_t) + sizeof(fidl_vector_t)
const baseBatchSize int = 32
An interactive verion of this example is hosted on the Go
Playground.
Contributing
fx set core.x64 --with //tools/fidl/measure-tape/src:host
fx build
Then
fx measure-tape \
-json out/default/fidling/gen/sdk/fidl/fuchsia.images/fuchsia.images.fidl.json \
-json out/default/fidling/gen/sdk/fidl/fuchsia.ui.gfx/fuchsia.ui.gfx.fidl.json \
-json out/default/fidling/gen/sdk/fidl/fuchsia.ui.input/fuchsia.ui.input.fidl.json \
-json out/default/fidling/gen/sdk/fidl/fuchsia.ui.scenic/fuchsia.ui.scenic.fidl.json \
-json out/default/fidling/gen/sdk/fidl/fuchsia.ui.views/fuchsia.ui.views.fidl.json \
-target-type fuchsia.ui.scenic/Command \
-target-binding hlcpp \
-h-include-path lib/ui/scenic/cpp/commands_sizing.h \
-out-h sdk/lib/ui/scenic/cpp/commands_sizing.h \
-out-cc sdk/lib/ui/scenic/cpp/commands_sizing.cc
Testing
fx set core.x64 --with //tools/fidl/measure-tape:tests
fx test measure-tape_test