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.
To add a measure tape to your project, use the measure_tape
template:
measure_tape("measure_tape_for_targettype") { target_binding = "hlcpp" target_types = [ "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_types
key indicates the list of FIDL target types for which to generate a measure tape. Target types 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
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.
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-types 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
fx set core.x64 --with //tools/fidl/measure-tape:tests fx test measure-tape_test