本文件將說明計算大小的最佳方法,以及 將元素加入向量時,其中的位元組和處理方式。這應該是 以便一次最大化可批次處理的元素數量 同時滿足管道寫入核心上限
摘要
如要透過管道盡可能提高處理量,批次處理大量回應是常見的做法 分為多個向量,例如使用分頁技術 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)
,加上
內容,也就是加入每個欄位的內容。
欄位的大小相對容易,有許多是基本或包裝函式
因此會產生 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 個位元組
sizeof(fidl_message_header_t)
,來自 zircon/fidl.h。
接著,向量有一個 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
「default」為 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
」的內容:fuchsia.ui.input.Command
的標題:24 個位元組,例如sizeof(fidl_xunion_t)
- 變化版本「
set_hard_keyboard_delivery
」的內容: - 結構
SendPointerInputCmd
:52 個位元組 - 對齊 8 個位元組的邊框間距:4 個位元組
因此總大小為 104 個位元組。