本文档介绍了计算 元素添加到矢量时的字节和句柄。此值应为 以尽可能增加一次性批量处理的元素数量 同时满足内核写入次数上限。
摘要
为了通过某个通道最大限度地提高吞吐量,常见的做法是批量处理大型响应 表示为多个向量,例如使用分页和 API。由于信道的上限为 64K 字节和 64 处理时,就会出现一个问题,那就是 可以在矢量中批量处理,以达到容量上限(然而, 字节大小和句柄计数阈值)。
以下内容的关键参考文档是 FIDL 线 format 规范。
下面列举了各种示例,说明了最大限度提高分页次数的最佳方法:
蓝牙 WatchPeers
方法
以下面的 WatchPeers 方法为例,
fuchsia.bluetooth.sys.Access
协议,定义如下:
WatchPeers() -> (vector<Peer>:MAX updated, vector<bt.PeerId>:MAX removed);
首先,请求或响应前带有标头,即固定的 16 个字节或
sizeof(fidl_message_header_t)
(如此处定义)。
每个矢量都有一个 16 个字节的标头 sizeof(fidl_vector_t)
,后跟
内容。
由于 bt.PeerId
是一个 struct{uint64}
(此处已定义),因此它也是一种
固定的 8 个字节,因此 removed
向量的内容是
元素 * 8 个字节。
接下来,我们需要估算 Peer
的大小,定义为
表格。表本质上是信封矢量,
其中每个信封都指向字段内容。估算大小必须
分两步完成:
- 确定使用的最大字段序数(也称为
max_set_ordinal
) - 确定每个呈现字段的大小
Peer
的大小则是表标头,即 sizeof(fidl_table_t)
为 16
个字节 - 加上最大的序号 * 信封标头(16 个字节),即
max_set_ordinal * sizeof(fidl_envelope_t)
- 加上
content,也就是添加每个呈现字段的内容。
字段的大小相对容易,其中许多是基元或封装容器,
因此得到 8 个字节(由于填充)。bt.Address
字段
也为 8 个字节,因为它的定义缩减为 struct{uint8;
array<uint8>:6}
。string
字段是字节矢量,即
sizeof(fidl_vector_t) + len(name)
进行填充,并将其填充到最接近的 8 个字节边界。
风景优美的Enqueue
方法
考虑使用 排队
fuchsia.scenic.Session
协议,定义如下:
Enqueue(vector<Command>:MAX cmds);
请求或响应前有标头,即固定的 16 个字节或
zircon/fidl.h 中的 sizeof(fidl_message_header_t)
。
然后,矢量有 16 个字节的标头 sizeof(fidl_vector_t)
,后跟
矢量内容,也就是实际的命令。因此,在
每个命令的大小,那么固定大小为 32
字节。
命令是值为 24 的并集
字节标头(即 sizeof(fidl_xunion_t)
),后跟内容,即 8
字节对齐。
Command
联合内容的大小取决于所选的变体。这个
示例使用类型为 input
的变体
fuchsia.ui.input.Command
。
(景观命令的)input
变体本身就是一个并集,它会添加
另一个 24 个字节的标头,后跟该联合的内容,例如
send_pointer_input
(类型)
SendPointerInputCmd
。
SendPointerInputCmd
的简化定义以及所有传递式
下面提供了通过此结构体的可到达类型:
type SendPointerInputCmd = struct {
compositor_id uint32;
pointer_event PointerEvent;
};
type PointerEvent = struct {
event_time uint64;
device_id uint32;
pointer_id uint32;
type PointerEventType;
phase PointerEventPhase;
x float32;
y float32;
radius_major float32;
radius_minor float32;
buttons uint32;
};
type PointerEventType = flexible enum {
// members elided
};
type PointerEventPhase = flexible enum {
// members elided
};
枚举 PointerEventType
和 PointerEventPhase
默认为 uint32
的底层表示形式。您
可以缩减 SendPointerInputCmd
的大小到结构体:
struct {
uint32; // 4 bytes, total 4
// 4 bytes (padding due to increase in alignment), total 8
uint64; // 8 bytes, total 16
uint32; // 4 bytes, total 20
uint32; // 4 bytes, total 24
uint32; // 4 bytes, total 28
uint32; // 4 bytes, total 32
float32; // 4 bytes, total 36
float32; // 4 bytes, total 40
float32; // 4 bytes, total 44
float32; // 4 bytes, total 48
uint32; // 4 bytes, total 52
};
因此,SendPointerInputCmd
结构体的大小为 52 个字节。有关
有关结构体大小计算的信息,请参阅失去结构的艺术
打包。
现在,您已经确定了命令所有部分的大小,接下来添加总大小:
fuchsia.ui.scenic.Command
的标头:24 个字节,即sizeof(fidl_xunion_t)
- 变体为“
input
”的内容: <ph type="x-smartling-placeholder">- </ph>
fuchsia.ui.input.Command
的标头:24 个字节,即sizeof(fidl_xunion_t)
- 变体为“
set_hard_keyboard_delivery
”的内容: - 结构体
SendPointerInputCmd
:52 个字节 - 要对齐到 8 个字节的内边距:4 个字节
总计大小为 104 个字节。