RFC-0032:高效信封

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

這項 FTP 建議採用更精簡的信封編碼方式。

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

「Turning Envelopes into Postcards」(將信封變成明信片)

拒絕原因

這項 RFC 最初於 2019 年 2 月 21 日獲得接受。FIDL 團隊在 2019 年大部分時間都致力於穩定線路格式,並在第 3 季和第 4 季全力以赴,遷移作業已於 2019 年 12 月 1完成。

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

不過,隨著工作展開,且 12 月 1的期限逼近,FIDL 團隊決定延後實作有效率的信封變更,並將這項工作延至 2020 年。與其他穩定性工作相關的變更不同,有效率的封包只是節省了記憶體大小,而且節省的空間非常小,尤其是與 FIDL 線路格式的其他方面 (例如表格的密集格式) 相比。延期是為了降低專案風險而進行的計算,縮減範圍後,按時完成所有工作的機率就會提高。FIDL 團隊的工作時間也是如此。

延後期限至今已將近 18 個月,高效信封早已被遺忘。2020 年的重大效能工作顯示,這項異動不會造成重大影響。

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

與其他 RFC 的關係

2021 年 6 月,我們重新探討這個主題,並使用目標基準評估成效。這項提案最終獲得接受,並在 RFC-0113 中重新導入。

摘要

這項 FTP 建議採用更精簡的信封編碼方式1

提振精神

信封是可擴充、可演進資料結構 (表格和可擴充聯集) 的基礎。信封的線路格式更精簡有效率,因此這些可擴充的結構體能用於更多情境,提升效能並縮減線路大小。

設計

建議的信封格式如下:

圖:64 位元小端序字組、MSB 32 位元大小、16 位元 handle_count、
16 位元保留

現有信封格式相比:

  • 大小欄位維持不變 (32 位元)。
    • 大小包括可能以遞迴方式編碼的任何子物件大小。
    • 舉例來說,vector<string> 的大小包括外部向量的內部字串子物件大小。
    • 這與目前封包實作的 size 欄位現有行為相符。
  • 保留 16 位元。
    • 解碼器必須驗證保留位元是否為零。
    • 如果我們日後想使用保留位元,應改為修訂線路格式。
      • 應更全面地思考 FIDL 的保留位元,確保規格間的行為一致。
      • 具體來說,FIDL 沒有解碼器忽略任何位元的先例:線路上的所有位元都已定義和指定。
      • 這是最簡單的決定,也就是要求變更線路格式,而不是啟用向前相容性,以便在決定保留位元政策之前,保持簡單。
  • 控制代碼計數為 16 位元,而非 32 位元。
    • 目前無法透過 Zircon 管道傳送超過 64 個控制代碼,我們認為 16 位元足以因應未來需求。
    • handle_count 包含所有遞迴子物件的控制代碼計數。
  • 已捨棄「存在/缺席」欄位。
    • 如果大小或 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。由於處理兩種線路格式的程式碼都會存在,建議您使用上述其中一種軟轉換方法,製作軟轉換是否可行的原型。這類原型設計工作也可能產生一般策略,以因應未來重大線路格式變更,這可能很有價值。 如果不是,那就沒辦法,只能硬性轉移。

無論是軟性或硬性轉移,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 位元。
    • 32 位元的大小是否合理?
    • 16 位元控點是否合理?
  • 本提案的依據 rfc-0026 建議將資料直接內嵌至信封,適用於 <= 32 位元的型別。
    • 我們決定從這項提案中撤銷內嵌功能,因為這會大幅增加實作複雜度,而且除非有大量可內嵌的欄位,否則效益不大。
    • 我們正在努力,希望更全面地思考選用性,例如將選用欄位分組到單一選用結構體中。這類工作可能會使內嵌帶來的任何好處過時。

既有技術和參考資料

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

提案。 已移除內嵌、所有位置的封裝,以及將字串/向量計數移出行外。


  1. 這個 FTP 是以 rfc-0026 為基礎,但包含行外封包 

  2. 請注意,目前空白 (零欄位) 結構體在網路上佔用一個位元組。