最大分页数

本文档介绍了计算 元素添加到矢量时的字节和句柄。此值应为 以尽可能增加一次性批量处理的元素数量 同时满足内核写入次数上限。

摘要

为了通过某个通道最大限度地提高吞吐量,常见的做法是批量处理大型响应 表示为多个向量,例如使用分页和 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 的大小,定义为 表格。表本质上是信封矢量, 其中每个信封都指向字段内容。估算大小必须 分两步完成:

  1. 确定使用的最大字段序数(也称为 max_set_ordinal
  2. 确定每个呈现字段的大小

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
};

枚举 PointerEventTypePointerEventPhase 默认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 个字节。