RFC-0114:在 FIDL 信封內內嵌小型值

RFC-0114:內嵌於 FIDL 信封中的小值
狀態已接受
區域
  • FIDL
說明

這個 RFC 建議變更 FIDL 線路格式,將 <= 4 個位元組的值內嵌在信封內文中。

變更
作者
審查人員
提交日期 (年/月)2021-06-24
審查日期 (年/月)2021-07-21

摘要

這個 RFC 提議採用 FIDL 傳輸格式變更,將 <= 4 個位元組的值內嵌在信封主體中。

提振精神

這項變更的原因是改善 FIDL 資料表和聯集 (即目前使用信封的版面配置) 的效能。

FIDL 聯集和資料表使用稱為信封的非行外物件共用表示法。外線指標是編碼和解碼的已知負擔來源。小型物件可以內嵌在信封本身中,無需擔心外列的負擔。

此外,在某些情況下,也可以減少分配金額。您可以直接將物件儲存在信封中,不必為物件分配出外線位置,並將其從信封指向該位置。

設計

這個 RFC 設計假設 RFC-0113 已獲核准,防護效率高的信封。

以下類型將採用新的內嵌值格式:

  • 布林值
  • 浮點值 32
  • uint8、uint16、uint32
  • int8、int16、int32
  • 版面配置為 uint8、uint16、uint32、int8、int16、int32 的列舉
  • 位元 s with layout uint8、uint16、uint32、int8、int16、int32
  • 控制代碼、client_end、server_end
  • struct 小於 4 個位元組
  • 陣列大小小於 4 個位元組

如果日後新增的值類型小於 4 個位元組,則除非另有說明,否則這些新類型的值也會使用內嵌值格式。

新格式可透過 C-struct 表示法描述:

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

InlinedValueEnvelopeOutOfLineWireEnvelope 的線形表示法都有重疊的 flags 欄位。flags 中的 LSB 會指出是否使用內嵌表單:1 代表內嵌表單,0 代表非行。所有未使用的標記位元都必須為 0

FIDL 中只有單一標準資料表示法。 存在大小最多 4 個位元組的值,且值超過 4 個位元組的值「必須」使用外行表示法。收到錯誤表示法的值「必須」觸發解碼錯誤。缺少的信封會繼續使用零信封表示法,也就是說,它們一律會以外框表示。

實作

這項變更需要複雜的遷移作業。不過,這項遷移可搭配其他傳輸格式遷移作業,大幅降低實務成本。

效能

內嵌欄位時,LLPP 的編碼時間會大幅縮短 (CL):

設定所有欄位的編碼時間 (以奈秒為單位):

# 個欄位 使用前 使用後
1 178 奈秒 147 奈秒
16 720 奈秒 325 奈秒
256 9396 奈秒 2909 奈秒

這張圖表顯示的編碼時間取決於資料表所含欄位數量的函式。表格中所有欄位皆已設定。

先前未測量解碼時間,但由於解碼演算法遵循與編碼類似的一系列步驟,因此也會大幅改善。

此外,在某些情況下,繫結可以避免為小型值進行配置,進一步提升效能。

人體工學

這個 RFC 允許繫結避免進行小數值配置,但不規定必須進行配置。如果繫結變更,用於處理這些類型的 API 最終可能會與處理需要分配的其他類型 API 有所不同。這種不一致可能會導致人體工學降低,因此必須謹慎行事以避免這種情況。

回溯相容性

這項變更所需的遷移程序會破壞 ABI 相容性。

不過,變更生效後,對類型變更的 ABI 相容性並不會產生任何影響。這項變更前後所有 <= 4 位元組的類型都無法保證 ABI 的 ABI 相容性。

這項變更可能破壞來源相容性。RFC 無須變更原始碼相容性變更,但如果繫結 MAY 改善繫結效能或其他原因,或許會選擇進行來源相容性破壞性變更。

安全性考量

這對安全性沒有影響。

隱私權注意事項

這不會影響隱私權。

測試

系統會使用多種策略來測試變更:

  • 每個繫結的自訂單元測試。
  • GIDL 合規套件。
  • FIDL 相容性測試。

說明文件

傳輸格式說明文件需要更新。

您必須在 API 評分量表中記錄效能的取捨,才能據以做出欄位大小決策。

缺點、替代方案和未知

缺點

這個提案的主要缺點是複雜度提高。現在有兩種值的表示法:內嵌和外行,視類型而定,而切換行為可能有 4 位元組的閾值。

替代方法:8 位元組內嵌值

這個 RFC 建議使用 4 個位元組以下的內嵌值。這是因為至少在實作與高效信封時一併實作時,可能無法內嵌 8 位元組值。

這是因為繫結必須支援未知的信封。不明信封送達時,無法得知類型資訊。因此,這會指出其是否指向外線物件,進而變更解碼器的行為。因此,值本身需要有一些資訊,用來指出它是以內嵌或外行格式進行結構。

如果信封大小為 8 個位元組,且內嵌的值是 8 個位元組,則如果該值是內嵌或外行格式,就不需要儲存任何備用值。

因此,8 位元組的內嵌值與有效率的信封不相容。必須選擇不使用有效率的信封,或縮減可內嵌的值的大小。這個 RFC 選擇了第二種選擇,因為這個方向最有可能改善效能。

先前的圖片和參考資料

RFC-0113 引入有效率的信封,成為此 RFC 中使用的信封結構的基礎。