RFC-0114:在 FIDL 信封中內嵌小值 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 這份 RFC 建議修改 FIDL 電報格式,將大小小於 4 個位元的值內嵌至信封主體中。 |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-06-24 |
審查日期 (年-月-日) | 2021-07-21 |
摘要
這份 RFC 建議修改 FIDL 線路格式,將大小小於 4 個位元組的值內嵌至信封主體中。
提振精神
這項變更的動機是為了改善 FIDL 資料表和聯集 (即目前使用信封的版面配置) 的效能。
FIDL 聯集和資料表會使用稱為封套的離線物件共用表示法。離線指標是已知的編碼和解碼額外負擔來源。小型物件可在信封內部內嵌,避免需要離線額外處理。
此外,在某些情況下,您也許可以減少分配量。您可以直接將物件儲存在信封中,而非為物件分配離線位置,然後從信封指向該位置。
設計
此 RFC 設計假設 RFC-0113 已獲得核准,因為這項 RFC 會引入高效率的封套。
下列類型將採用新的內嵌值格式:
- 布林值
- float32
- uint8、uint16、uint32
- int8、int16、int32
- 版面配置為 uint8、uint16、uint32、int8、int16、int32 的列舉
- 位元,版面配置為 uint8、uint16、uint32、int8、int16、int32
- handle、client_end、server_end
- 結構體大小小於 4 位元組
- 陣列大小 <= 4 位元組
如果日後新增的值類型大小小於或等於 4 個位元組,則也會使用內嵌值格式,除非另有說明。
新格式可透過 C 結構表示法描述:
// An envelope corresponds to a union value or an entry in a table.
struct Envelope {
union {
// Inlined values have the same envelope structure for both wire and
// decoded formats.
InlinedValueEnvelope inlined_value_envelope;
// Out-of-line values have a different structure on the wire and in
// decoded format.
union OutOfLineEnvelope {
// Wire representation.
OutOfLineWireEnvelope out_of_line_wire_envelope;
// Decoded representation.
void* decoded_data;
};
};
};
struct InlinedValueEnvelope {
// A <= 4-byte value stored little-endian and 0-padded up to 4-bytes.
uint8_t value[4];
// Number of handles within the envelope.
uint16_t num_handles;
// Bit 0 of flags is 1 to indicate the inline representation is used and
// the envelope is present.
uint16_t flags;
};
struct OutOfLineWireEnvelope {
// Number of bytes recursively within the envelope.
uint32_t num_bytes;
// Number of handles recursively within the envelope.
uint16_t num_handles;
// Bit 0 of flags is 0 to indicate the out-of-line representation is used.
uint16_t flags;
}
兩個線路表示法 InlinedValueEnvelope
和 OutOfLineWireEnvelope
都有重疊的 flags
欄位。flags
中的 LSB 會指出是否使用內嵌表單:1
代表內嵌,0
代表離線。所有未使用的旗標位元都必須是 0
。
FIDL 中只有單一標準資料表示法。大小為 4 個位元組的現值必須內嵌,而超過 4 個位元組的值則必須使用離線表示法。收到錯誤表示法的值時,必須觸發解碼錯誤。缺少的信封會繼續使用零信封表示法,也就是說,這些信封一律會以離線表示法表示。
實作
這項變更需要複雜的遷移作業。不過,這項遷移作業可與其他電報格式遷移作業結合,實際上可降低成本。
成效
當欄位內嵌時 (CL),LLCPP 的編碼時間會大幅縮短:
設定所有欄位後的編碼時間 (以奈秒為單位):
# 欄位 | 使用前 | 使用後 |
---|---|---|
1 | 178 毫秒 | 147 奈秒 |
16 | 720 毫秒 | 325 毫秒 |
256 | 9396 秒 | 2909 毫秒 |
這張圖表顯示編碼時間與資料表欄數的關係。資料表中的所有欄位都已設定。
我們並未測量解碼時間,但由於解碼演算法會遵循與編碼相似的一系列步驟,因此也預期會大幅改善。
此外,在某些情況下,繫結可避免為小值進行配置,進而進一步提升效能。
人體工學
這份 RFC 允許繫結避免為小值進行配置,但並未規定必須如此。如果繫結確實有所變更,用於處理這些類型的 API 可能會與用於處理需要配置的其他類型的 API 不同。這種不一致性可能會導致人體工學變差,因此必須小心避免。
回溯相容性
這項變更所需的遷移作業會破壞 ABI 相容性。
不過,一旦變更生效,就不會影響類型變更的 ABI 相容性。所有 <= 4 位元組類型都無法保證在變更前後,類型變更的 ABI 相容性。
這項變更可能會導致來源不相容。RFC 並未要求進行任何破壞原始碼相容性的變更,但繫結可能會選擇進行破壞原始碼相容性的變更,以改善繫結效能或出於其他原因。
安全性考量
這不會影響安全性。
隱私權注意事項
這不會影響隱私權。
測試
我們會使用多種策略來測試變更:
- 每個繫結中的自訂單元測試。
- GIDL 合規套件。
- FIDL 相容性測試。
說明文件
需要更新線路格式說明文件。
您必須在 API 評分標準中記錄效能取捨,以便做出欄位大小的決定。
缺點、替代方案和未知事項
缺點
這項提案的主要缺點是複雜度增加。目前有兩種值表示法,分別是內嵌和離線,取決於類型。您可能會訝異,切換行為有 4 個位元組的門檻。
替代做法:8 位元組內嵌值
這份 RFC 建議內嵌 4 個位元組以下的值。原因是,至少在與高效率信封搭配實作時,似乎無法內嵌 8 個位元組的值。
這是因為繫結項必須支援不明信封。不明信封抵達時,系統不會提供任何類型資訊。因此,我們無法得知該物件是否指向離線物件,而這會影響解碼器的行為。因此,值本身必須包含一些資訊,指出其是否以內嵌或離線格式結構化。
如果信封大小為 8 個位元組,而內嵌的值為 8 個位元組,如果值採用內嵌或離線格式,就沒有可儲存的備用位元。
因此,8 個位元組的內嵌值與高效信封不相容。您必須做出選擇,要嘛不使用效率高的封套,要嘛減少可內嵌的值大小。這份 RFC 選擇了後者,因為這個方向似乎最有可能帶來最顯著的效能改善。
既有技術與參考資料
RFC-0113 介紹了高效率的封套,這也是本 RFC 中所用封套結構的基礎。