RFC-0032:高效信封

RFC-0032:高效率信封
狀態已遭拒
區域
  • FIDL
說明

這個 FTP 會為信封提供更精簡的編碼。

作者
提交日期 (年-月-日)2019-02-06
審查日期 (年-月-日)2019-02-21

「將信封轉換為明信片」

拒絕理由

這項 RFC 已於 2019 年 2 月 21 日初步通過。FIDL 團隊在 2019 年大部分時間內致力於穩定線路格式,並在第三季和第四季全力投入相關工作。遷移作業已於 2019 年 12 月 1 日完成。

穩定性改善工作涵蓋了多項變更:

不過,隨著工作進展,且 12 月 1 日的期限將至,FIDL 團隊決定暫緩實施高效信封變更,並將這項工作推遲到 2020 年。與其他變更不同,這些變更是穩定性努力的一部分,而效率高的封套只是記憶體內的大小節省,而且非常小,尤其是與 Fidl 電報格式的其他部分 (例如 tables' dense format) 相比。延後是專案風險降低計算的結果,藉由縮小範圍,可提高按時完成所有工作的機率。這也是 FIDL 團隊的工作時間表。

延後 18 個月後,我們已經快要忘記高效信封了。2020 年有重大的效能改善,這項異動不會對我們造成重大影響。

是時候面對現實了,這不會發生。已遭拒。

與其他 RFC 的關係

2021 年 6 月,我們重新探討這個主題,並以指定基準評估成效。這項變更已確定,RFC-0113 也提出重新導入這項變更的建議,並獲得接受。

摘要

這個 FTP 建議為信封提供更精簡的編碼1

提振精神

信封是可擴充、可進化的資料結構 (表格和可擴充的聯集) 的基礎。封套的線路格式更精簡且高效,因此可在效能和線路大小較重要的更多情境中使用這些可擴充的結構。

設計

建議的封包格式如下:

圖:64 位元小端字詞,MSB 32 位元大小,16 位元 handle_count,16 位元保留

現有的封套格式相比:

  • 大小欄位保持不變 (32 位元)。
    • 大小包括任何可能遞迴編碼的子物件大小。
    • 舉例來說,vector<string> 的大小包含外部向量內部字串子物件的大小。
    • 這與目前信封實作大小欄位的現有行為相符。
  • 保留 16 位元。
    • 解碼器必須驗證保留位元是否為零。
    • 如果我們日後想使用保留位元,則應改用線路格式。
      • 您應從更全面的角度思考 FIDL 的保留位元,以便在各規格中維持一致的行為。
      • 特別是,在 FIDL 中,解碼器忽略任何位元都沒有先例:線路上的所有位元都已定義和指定。
      • 這項決定是最簡單的做法,只需變更線路格式,而非啟用前向相容性,讓事情保持簡單,直到決定有關保留位元的政策為止。
  • handle_count 為 16 位元,而非 32 位元。
    • 目前無法透過 Zircon 管道傳送超過 64 個句柄,我們認為 16 位元可提供足夠的空間來滿足未來的需求。
    • handle_count 包含所有遞迴子物件的句柄計數。
  • 「有/無」欄位已刪除。
    • 在 size 或 handle_count 欄位中,非零值代表存在。
    • 大小和句柄計數欄位都為零,表示沒有。
  • 大小為 UINT32_MAX 且句柄計數為 0 的內容很特別:它代表存在的封套內容,但大小為零。
    • 如果零大小的空結構體2成為現實,這個選項就會保留供日後使用,且不會對目前的解碼器施加任何效能或複雜度懲罰。我們希望現在就提及這點,以免日後可能的實作方式破壞線路格式。
    • 我們可以改為竊取其中一個保留位元。我們對此沒有強烈的意見;只要有辦法將「存在但大小為零」的信封與 FIDL_ALLOC_ABSENT 區分開來,就沒問題。很高興能達成共識。

假設解碼器知道信封內容的靜態類型 (結構定義),則可能會使用指向信封資料的指標覆寫信封。如要瞭解如何處理內容類型不明的封套,請參閱「不明資料」一節中的建議。

用於編碼/解碼表單的 C/C++ 結構體

信封的編碼格式可由編碼或解碼格式的聯集表示。

typedef union {
  struct {
    uint32_t size;
    uint16_t handle_count;
    uint16_t reserved;
  } encoded;
  void* data;
} fidl_envelope_t;

static_assert(sizeof(fidl_envelope_t) == sizeof(void*));

不明資料

接收器 (驗證器和解碼器) 在可進化的資料結構中使用時,可能不知道封套的類型。如果接收端不瞭解類型,則可對信封進行最少的剖析,並略過信封。

  • 信封的大小決定要略過的離線資料量。
  • 如果信封的句柄數量不為零,驗證工具就必須處理指定數量的句柄。
    • 預設處理行為必須是關閉所有句柄。
  • 如果解碼器想要就地解碼,則可能會使用指向信封內容的指標覆寫不明信封。
    • 如果解碼器確實使用指標覆寫封套,就會遺失封套中的大小和句柄計數資訊。繫結可能會提供機制,讓解碼器在覆寫封套之前儲存大小和句柄計數資訊;這個 FTP 不會針對此機制如何運作發表意見。

導入策略

這項 FTP 是破壞性的線路格式變更。

雙方 FIDL 同儕都必須瞭解新的封套格式,並將這項資訊傳達給對方,才能使用新格式。因此,這通常會被視為硬轉換。由於這項 FTP 並未新增任何新功能,如果我們決定將其設為硬轉移,作者建議將這項變更與其他線路格式變更 (例如建議的序數大小變更) 一併處理。

不過,您可以進行軟性轉換。兩種方法如下:

  1. 交易訊息標頭中含有 uint32 保留/旗標欄位。我們可以為發起端同等級保留 1 位元,表示該端級瞭解新的線路格式,並分階段進行軟性轉換:
    1. 確保所有用戶端和伺服器都能解讀舊版和新版的線路格式。我們會繼續使用舊的傳輸格式。
    2. 請讓對等端在交易訊息標頭中設定位元,啟用新的線路格式。如果雙方都已設定位元,則雙方都能切換至新的線路格式。
    3. 當軟性轉換已在所有層中推出後,所有 Fuchsia 都能使用新的線路格式。我們可以移除交易訊息標頭中的位元設定。
    4. 刪除舊線路格式的程式碼,並取消保留交易訊息標頭位元。
  2. 我們可以使用「[WireFormat=EnvelopeV2]」屬性 (或類似的屬性) 修飾特定的 FIDL 訊息類型、介面或兩者,藉此指出訊息/介面應使用新的線路格式。
    1. 雖然使用 WireFormat 屬性修飾介面似乎能與線路格式變更保持一致,但在結構體上實作 WireFormat 變更應該會更容易,因為結構體可用於不同介面,而繫結需要額外的邏輯來判斷使用結構體的內容。
    2. 建議介面 [WireFormat] 屬性只影響介面方法引數的線路格式,而不會遞迴影響引數的結構體。
    3. 這可讓您部分遷移並選擇採用新的線路格式,讓團隊可自行決定遷移速度。
    4. 一旦所有結構體和介面都具有 [WireFormat] 屬性,我們就可以放棄舊的線路格式、假設所有結構體和介面都使用新的線路格式,並忽略該屬性。

這兩種軟性轉換方法都需要大量的開發時間、測試時間和出錯空間。實作程式碼以正確執行任一方法、執行計畫,並順利移除舊程式碼,這需要付出大量心力。

我們很可能會同時提供程式碼來處理舊版和新版的線路格式;否則,在實作支援新線路格式的同時,就無法逐步發布 CL。由於程式碼會處理兩種線路格式,建議您製作原型,以便使用上述其中一種軟性轉換方法,判斷軟性轉換是否可行。這類原型設計工作也可能會帶來一般策略,用於處理未來的重大新聞格式變更,這可能很有價值。 如果沒有,那麼c'est la vie,只能進行硬轉移。

無論是軟性或硬性轉換,在 Fuchsia 中,凡是手動推出 FIDL 訊息的任何例項,都必須升級至新的線纜格式。

回溯相容性

建議的線路格式變更應與 API (來源) 相容。任何手動編譯的 FIDL 程式碼都必須更新,才能處理新的線路格式。

傳輸格式變更與 ABI 不相容。您可以透過「實作策略」一節所述的策略,實現 ABI 相容性。

成效

這項 FTP 可大幅縮減信封所需的大小,這似乎是整體的重要淨效益。不過,如果可擴充資料結構因效率更高而變得更普遍,這可能會因為使用量增加而抵銷,進而導致整體訊息更不精簡,且動態配置更頻繁,而非使用不可擴充資料結構。

人體工學

  • 更有效率的可擴充資料結構可用於效率至關重要的更多情境,因此使用者不必太擔心效能問題,而且可在先前需要使用不可擴充結構的情況下,享有可擴充性帶來的好處。
  • 我們甚至建議您在預設情況下使用表格來處理 Fidl 資料結構,並將結構體保留給高效能情境。
    • 可擴充的聯集 (RFC-0061) 已嘗試移除靜態聯集。

說明文件

  • 需要更新線路格式說明文件。
  • 更新說明文件時,應將信封解釋為第一類概念:這樣一來,讀者遇到可選性和可延伸資料結構的電報格式時,就能進行更好的認知區塊處理
  • 我們應更新 FIDL 樣式指南,針對應使用可擴充類型的時機提供建議。

安全性

這項 FTP 應不會對安全性造成重大影響。

這項 FTP 的安全性優點之一,就是會移除舊版格式中大小和指標重複的資訊。先前,您可能會收到大小/句柄非零值的封套,以及 FIDL_ALLOC_ABSENT,或是大小/句柄為零的封套,以及 FIDL_ALLOC_PRESENT。這項功能需要額外的驗證檢查,但現在已不需要。

測試

  • 由於這個 FTP 會變更信封的線路格式,我們認為現有的 FIDL 測試套件 (尤其是相容性測試) 將可充分測試所有使用信封的情況。
  • 如果我們同意以軟性轉換方式導入線路格式變更 (請參閱「導入策略」一節),我們會新增測試,讓同儕進行協商,並可能改用新的線路格式。

缺點、替代方案和未知事項

如果我們認為這項提案的效率提升效果不值得實施,可以保留現有的線路格式。

設計決策

在這個 FTP 提出建議的同時,我們會積極尋求意見,並就以下決策達成共識:

  • 我們要考慮採用軟性轉換還是硬性轉換?如要瞭解優點和缺點,請參閱「導入策略」一節。
  • 我們建議使用 32 位元做為大小、16 位元做為句柄,並保留 16 位元。
    • 大小是否合理?
    • 是否適合使用 16 位元句柄?
  • 這項提案源自 rfc-0026,該提案建議將資料直接內嵌至信封中,適用於長度小於或等於 32 位元的類型。
    • 我們決定從這項提案中撤銷內嵌功能,因為這會大幅增加實作複雜度,且除非有大量可內嵌的欄位,否則提供的效益不大。
    • 我們正在努力讓選用性更全面,例如將選用欄位分組為單一選用結構體。這類工作可能會讓內嵌作業帶來的任何好處變得毫無用處。

既有技術與參考資料

這個 FTP 是 rfc-0026 的簡化版本,由於整個 FTP 沒有獲得足夠的共識,因此遭到拒絕。

提案。內嵌、隨處放置信封,以及將字串/向量計數器移出行外,都已移除。


  1. 這個 FTP 是根據 rfc-0026 建立,但只使用離線封套 

  2. 請注意,目前空白 (零欄位) 結構體會在傳輸線上占用一個位元組。