RFC-0026:處處可見

RFC-0026:隨處收信
狀態已遭拒
領域
  • FIDL
說明

將信封設為輕巧的兩倍以上,提升現有信封格式的效能。請用信封做為參照所有外部物件的唯一方法。這可提高傳輸方式的一致性,以及通訊協定設計和實作的統一性。

作者
提交日期 (年-月-日)2019-01-19
審查日期 (年-月-日)2019-02-04

拒絕原因

有鑑於此 RFC 相關意見和評論數量龐大,我們決定 撤銷 (例如自行拒絕) 提案。 雖然如此,我們還是有不錯的點子:我們會採納這些點子 再以較小的 RFC 形式 並在各自的 RFC 中區隔出獨立功能

RFC-0032 是從這個 RFC 中增加而來。

摘要

這個 RFC 有兩個目標:

  1. 如何改善現有 envelope 格式的效率: 信封是輕巧的兩倍以上。
  2. 請用信封做為參照「所有」外部物件的唯一方法。 這樣可提高線路格式的一致性, 通訊協定設計和實作

(1) 和 (2) 的副作用是選擇性 (是否可為空值) 適用於所有型別、控點、向量 字串、資料表和 (可延伸) 聯集1

提振精神

信封是可擴充可擴充資料結構的基礎 (資料表和可延伸聯集)。 更有效率的信封設計,可以使這些延伸結構 在效能和電線大小方面的重要性。

FIDL 也具有幾種適用於動態大小的廣泛類型 資料:向量與字串。 由於 FIDL 主要執行個體的大小,這些類型必須為非線形 是靜態的 如果可以使用信封來代表所有外部資料,我們可以簡化 同時降低執行成本和空間 。

此外,全方位且一致的方法也能受益於 FIDL 選用性 這有助於提高人體工學,比現行的類型更加完善 並簡化了使用者的心理模型 為 統一

設計

信封可以參照符合以下任一條件的資料:

  • ,類似於現有的信封格式,或
  • 內嵌,資料儲存在信封中。 可用於「小尺寸」固定大小及較少的類型 大於 64 位元

非線形信封

斷線信封為:

圖:外信封,64 位元小端子,較小的 48 位元尺寸
最低有效位元零,16 位元
handle_count

做為 C 結構體:

typedef struct {
  uint64_t size:48;  // Low bit will be 0
  uint16_t handle_count;
} fidl_out_of_line_envelope_t;

離線信封具有下列變更與現有信封的差異 格式:

  • 大小 (num_bytes) 是 48 位元,而非 32 位元,因此能更大 酬載。
    • 大小包括可遞迴的子物件大小 編碼。
      • 舉例來說,vector<string> 的大小包含 最外層向量的內部字串子物件。
      • 這與目前信封的現有行為相符 大小欄位中的值
    • 合法的 Outline 物件大小一律為 8,因為多行物件會對齊八位元組。 這表示 size % 8 == 0 表示
      • 大小欄位最低的三位元,因此 LSB 大小欄位 - 將會是 0
      • 信封的 LSB —因為大小欄位位於 所以一律為 0
      • 這非常重要,如下方代碼位元中所述。
    • 請參閱程式碼外的編碼大小 下方的信封 計算遞迴大小對效能的影響。
  • handle_count 為 16 位元,而非 32 位元。
    • 目前無法傳送 >由 64 個 Zircon 管道共同處理; 我覺得 16 位元可提供足夠空間,可以滿足未來的需求。
    • handle_count 包含所有遞迴的控制代碼數量 子物件。
  • 系統會捨棄在家狀態/不存在欄位。
    • 存在時間為 size 中的非零值,或 「handle_count」欄位中的值。
    • 代表不存在,代表 size 且兩者皆有 handle_count 欄位 值就會是 0
      • 這就是所謂的零信封

解碼器可能會用指標覆寫信封中的資料 假設他們知道信封內容的靜態類型 (結構定義)。 如需相關建議,請參閱「解碼器回呼」一節 如果內容類型不明,該如何處理信封。

代碼位元

非行內信封明確地佔了 以及佔用最多位元的控制代碼數量。 如信封一節所述,

  • 因為大小欄位下限的位元一律為零 (因為 大小是 8 的倍數
  • 信封的最低位元永遠是零。

我們稱之為信封最底邊的「標記位元」

  • 如果 Tag 位元為 0,代表信封的資料為「out-of-line」
  • 如果代碼位元是,信封的資料就會是「內嵌」

由於代碼位元是內嵌資料的一個位元,因此內嵌信封無法 能對需要 64 位元對齊的架構實際指標 指標會是 8 的倍數,並且需要最低三位元才能 零時差弱點 這有助於解碼器區分內嵌信封 而非實際的指標,因為解碼器通常會覆寫離線信封 —但不內嵌信封 — 以指標指向信封 內容。

內嵌信封

內嵌信封會編碼為:

圖:在線條信封中,64 位元小端子,最不重要的位元是
值 1 表示標記,保留 31 位元,然後內嵌 8、16 或 32 位元
資料

做為 C 結構體:

typedef struct {
  uint8_t tag:1;  // == 1
  uint32_t reserved:31;
  union {
    _Bool bool;
    uint32_t uint32;
    int32_t int32;
    uint16_t uint16;
    int16_t int16;
    uint8_t uint8;
    int8_t int8;
    float float32;
    zx_handle_t handle;  // Only when decoded (see Handles for more details)
  };
} fidl_inline_envelope_t;
  • 內嵌信封將 LSB 設為 1,藉此區分 落後信封及實際指標。
  • 信封上 32 位元的部分會用來表示內嵌值。 可以是 int8uint8int16uint16int32uint32float32bool 或帳號代碼。
    • 系統會使用 32 位元最低位元來表示值 如果該值小於 32 位元 微小元素表示法
  • 除非日後的 RFC 指定了 0,否則編碼器必須將保留的位元編碼為 0 也就是系統如何解讀這些位元
  • 解碼器和驗證工具「必須」忽略保留的位元 (除非日後的 RFC 除外) 指定如何解譯這些位元。
  • 解碼器應在解碼時保留內嵌信封。
    • 由於內嵌資料包含內嵌資料, 參照的替代程式碼,不需要根據 與原封不動的信封不同時的指標指標。

編碼器應該以行外或內嵌方式進行編碼嗎?

編碼器「必須」:

  • 如果類型為 bool、(u)int8、(u)int16,就將資料編碼為內嵌 (u)int32float32 或帳號代碼。 (事實上,如果型別是固定大小且 <= 32 位元)。
  • 為所有其他類型的資料即時編碼資料 (事實上,如果類型是 >= 64 位元或可變大小)。

帳號代碼

帳號代碼宣告有三種情境:

  1. 在無法擴充容器中的非選擇性控制代碼,例如struct S { handle h; };
  2. 在無法擴充容器中的選用的控制代碼,例如struct S { handle? h; };
  3. 在可延伸容器中的控制代碼,例如table T { handle h; }

以 (1) 來說,這是非可延伸容器中的非選擇性帳號代碼,我們建議 保留現有的線路格式 (uint32)。 在不可擴充的容器中, 紅包,因為信封的設計是選擇性地或 動態大小的資料

就 (3) 而言,擴展式容器中的控制代碼:因為信封是 可延伸容器的基礎,必須使用信封將 控制代碼。 如要對控點進行編碼,編碼器「必須」將其編碼為斷線的信封 其中 size 設為 0,handle_count 設為 1:

圖:小端的 64 位元資料欄位,底部 48 位元設定為
0 和 next 16 位元,表示 handle_count 已設為
1 分

此編碼會指示解碼器查詢 離線處理常式表格。 如果解碼器想就地解碼,則解碼器「必須」:

  • 在離線處理表中查詢控點,以判斷 實際帳號代碼值
  • 將代碼位元設為 1,以將信封從外部變更為內嵌。
  • 將 fidl_inline_envelope_t 結構的控點欄位設為 處理常式值。

圖:將最低有效位元標記設為小端的 64 位元資料欄位
1,保留 31 位元,接下來 32 位元
handle_value

如需經過編碼/解碼的控制代碼範例,請參閱範例一節。

這種雙重編碼/解碼格式與 和非線上和內置信封編碼。 雖然這會導致信封中的帳號代碼專門程式碼, 認為資料編碼越統一,越能保持一致; 而不是較為簡單、需要較多編碼的程式碼。

(2) 在無法擴充的容器中,我們也建議採用這個帳號代碼: 使用與網路相同的信封表示法 (3), 即雙外部編碼/內嵌解碼的雙重格式。 遺憾的是,這個選填帳號代碼的表現不如 現有的選用的處理線格式uint32。 不過,我們還是鼓勵使用信封表示法

  • 使用信封來輸入帳號代碼,與使用 任何選用類型的信封,
  • 在 FIDL 訊息與其他訊息中,選擇性帳號代碼相對罕見 類型2,因此額外的 4 個位元組的信封負擔 不會對郵件大小造成顯著影響
  • 保留現有 uint32 線路格式的可選控點 會產生三個編碼和三個不同的控制代碼程式碼路徑: 非選用、選用和處理信封。 使用信封表示法為選用功能,可省去一種編碼方式 和一個程式碼路徑,可提升統一性並減少專業領域 再也不是件繁重乏味的工作

的編碼 (2):非可延伸容器中的選用控點 — 明確列於設計決策中 一節,因為更精簡的 uint32 表示法代表選用 可考慮設定帳號代碼

弦樂和向量

不可為空值 String向量會儲存為 16 個位元組:

  • uint64 代表元素 (向量) 或位元組 (字串) 的數量。
  • 用於所在地/不存在/指標的 uint64

我們建議使用信封來代表字串和向量, 可為空值或不可為空值:

  • 元素數量 (向量) 或位元組 (字串) 遭到移出線外
    • 這可讓向量/字串以信封表示 (僅限)。 因此,信封就是唯一參照「任何」函式 在所有 FIDL 型別上以一致的方式呈現資料, 所有資料。
    • 向量/字串內容位於獨立的非線物件中 緊跟隨元素/位元組的計數
  • 系統會用信封判斷是否存在/不存在 非零個值。

請注意,向量元素的數量與信封大小不同:

  • 信封大小是向量元素數量乘以元素 大小
  • 如果向量含有子物件 (例如 vector<Table>vector<vector<string>>),信封大小包括 遞迴子物件。

可為空值字串/向量,以及可擴展容器中的字串/向量 表示方式與不可為空值字串和向量相同:零 信封是用來表示缺少字串/向量。

反之,如果字串/向量不可為空值,則當發生以下情況時,驗證工具「必須」發生錯誤 遇到零信封

對使用 C 繫結的程式碼來說,變更可能會破壞原始碼 該物件會預期 fidl_vector_tfidl_string_t 的記憶體版面配置 完全符合電線格式。 但是,我們可以在變更電匯格式之前,先實施轉換計畫 (例如將 C API 變更為使用函式或巨集),讓這項功能成為 柔和轉換

請注意,您仍可以將新的字串/向量版面配置表示 透過彈性陣列成員 (例如 struct { uint64 element_count; element_type data[]; };) 建立的 C 結構體。

選用 (可為空值) 類型

目前,結構體、字串、向量、控點、聯集、表格和可延伸 聯集可以選用 (可為空值)。

在任何地方使用信封,可使「所有」類型設為選用

  • 呈現選用資料是以空白形式儲存在信封中 或「內嵌」選項
  • 缺少的選用資料會以零信封儲存。

請注意,如果是小型類型,內嵌資料可以將選用類型儲存為 視容器對齊方式而定,僅做為非選用類型 Google Cloud 就是最佳選擇

已編碼/解碼表單的 C/C++ 結構

經過編碼的信封形式可以用 內封信封或外信封。 同樣地,已解碼的信封可以是內嵌的,也可以是指向信封的指標 或回呼決定的值 (請參閱解碼器 回呼部分查看詳細資料)。

typedef union {
  fidl_inline_envelope_t inline;            // Low bit is 1
  fidl_out_of_line_envelope_t out_of_line;  // Low bit is 0
} fidl_encoded_envelope_t;

typedef union {
  fidl_inline_envelope_t inline;  // Low bit is 1
  void* data;                     // Low bit is 0
  uintptr_t callback_data;  // Value determined by callback (see Decoder Callback)
} fidl_decoded_envelope_t;

static_assert(sizeof(fidl_encoded_envelope_t) == sizeof(void*));
static_assert(sizeof(fidl_decoded_envelope_t) == sizeof(void*));

不明資料

接收器 - 驗證工具與因此可能不知道 在資料表等可改良的資料結構中使用時的信封 或可延伸的聯集 如果接收者不知道信封類型:

  • 因此您可以放心忽略內嵌信封。
    • 帳號代碼「必須」以行內信封 (而非內嵌的信封) 編碼 這可以確保所有內嵌信封安全無虞。
  • 您可以利用最少的架構來剖析並略過離線信封。
    • 信封大小會決定要略過的閒置資料量。
    • 如果信封的帳號代碼不是零,則驗證工具「必須」處理 指定的帳號代碼
      • 系統預設的處理行為「必須」關閉所有帳號代碼。
    • 解碼器「可能」會覆寫未知信封,並指向 信封的內容 (如果想就地解碼)。
      • 如果解碼器確實以指標覆寫信封, 就會失去大小處理信封中的數量資訊。 如果這是問題,請參閱解碼器回呼 一節。

請注意,將大小嵌入外部信封中,就能快速 如果需要略過許多未知的類型,則透過 FIDL 訊息略過。

解碼器回呼

如「不明資料」一節中所述,「不明」 信封可能會被解碼器覆寫:如果發生這種情況 就會遺失大小和帳號代碼資訊 或者,解碼器 MAY 也可以附加回呼,以 處理信封並覆寫預設行為 回呼 API 看起來類似下列函式原型:

void set_unknown_envelope_callback(
    unknown_envelope_callback_t callback,  // a callback
    void* context                          // client-specific data storage
);

typedef uintptr_t (*unknown_envelope_callback_t)(
    const void* message,  // pointer to the envelope's containing message
    size_t offset,        // offset in the message where the unknown envelope is
    size_t size,          // the envelope's size
    size_t handle_count,  // the envelope's handle count
    const char* bytes,    // pointer to the envelope's data
    void* context         // a context pointer set via set_unknown_envelope_callback()
);

回呼會傳回 uintptr_t,讓解碼器用於覆寫 未知的信封。 讓解碼器從不明物件複製大小和處理常式數量 然後透過指向解碼器本身的指標 覆寫信封 自訂資料結構

線外信封編碼大小

此 RFC 規定外部信封必須具備正確 (遞迴) 以及用於呈現非行距的資料大小 這項規定可能會對編碼器造成額外負擔,因為如果 接收端預期會知道信封類型,而大小欄位是 不需要自行計算,因為解碼器可計算大小 3。 因此,編碼器可執行額外工作,但看不出來 好處。 這個引數也適用於帳號代碼計數。

不過,我們仍建議「必須」顯示尺寸和帳號代碼計數 原因如下:

  1. 一致性:要求大小意味著信封編碼是 無論是在可延伸容器中 不一定。 統一性越高,程式碼越少,認知模型也變得更加簡單。
  2. 我們日後可以變更這項資訊。 日後的 RFC 可以選擇使用 setinel 大小的值 (例如 UINT48_MAX),或預留大小欄位中的三個 LSB 之一, 表示大小不明,在這種情況下,解碼器必須週遊 ,並計算自身大小。 這項變更不會影響電線格式,因為 欄位保持不變 由於解碼器可實作 更新編碼器之前

整體而言,RFC 作者認為要求編碼不得為不明 可能過早最佳化,並採用簡單的 更一致、一致的設計 如果您認為日後應重新審視這項決定 (例如: 支援零複製向量 I/O 編碼器 不需要修補信封就能寫入正確大小 可以明確實作這個 API 的路徑

範例

選用的內嵌 uint 程式碼:

uint32? u = 0xdeadbeef;  // an optional uint: stored inline.

C++ 表示法:

    vector<uint8_t> object{
        0x01, 0x00, 0x00, 0x00,                          // inline tag
                                0xEF, 0xBE, 0xAD, 0xDE,  // inline data
    };

選用的 vector<uint16> 是離線儲存的:

vector<uint16>? v = { 10, 11, 12, 13, 14 };  // an optional vector<uint16>; stored out-of-line.

閒置大小為 24:

  • 在一行之外儲存的元素數量為 8 位元組,做為其次要物件
  • 向量內容 + 10 (5 個元素 * sizeof(uint16_t)),
  • = 18,會無條件進位至 24。

C++ 表示法:

    vector<uint8_t> object{
      0x18, 0x00, 0x00, 0x00, 0x00, 0x00,              // envelope size (24)
                                          0x00, 0x00,  // handle count
    };

    vector<uint8_t> sub_objects{
      // element count
      0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      // vector data
      0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00,
      0x0E, 0x00,
      // padding
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };

含有三個欄位的 table

table T { 1: int8 i; 2: reserved; 3: int64 j; } = { .i: 241, .j: 71279031231 };

C++ 表示法:

    // a table is a vector<envelope>, which is represented with an
    // out-of-line envelope
    vector<uint8_t> object{
      0x28, 0x00, 0x00, 0x00, 0x00, 0x00,              // envelope size (40)
                                          0x00, 0x00,  // handle count
    };

    vector<uint8_t> sub_objects{
      // vector element count (max table ordinal)
      0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      // vector[0], 1: int8, stored inline
      0x01, 0x00, 0x00, 0x00,                          // inline tag
                              0xF1, 0x00, 0x00, 0x00   // 241
      // vector[1], 2: reserved
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // zero envelope
      // vector[2], 3: int64, stored out-of-line
      0x08, 0x00, 0x00, 0x00, 0x00, 0x00,              // envelope size
                                          0x00, 0x00,  // handle count
      // vector[2] content
      0xBF, 0xB3, 0x8F, 0x98, 0x10, 0x00, 0x00, 0x00   // 71279031231
    };

帳號代碼:

handle h;  // decoded to 0xCAFEF00D

C++ 表示法:

    vector<uint8_t> encoded_form{
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              // envelope size
                                          0x01, 0x00,  // handle count
    };

    vector<uint8_t> decoded_form{
      0x01, 0x00, 0x00, 0x00,                          // inline tag
                              0x0D, 0xF0, 0xFE, 0xCA,  // inline data
    };

執行策略

這個 RFC 是破壞線格式變更。 FIDL 通訊端都需瞭解新的線路格式,並且 向同事 新的格式

可以進行柔性轉換。 以下為兩種做法:

  1. 交易訊息中有 uint32 保留/旗標欄位 標題。 我們可以保留 1 位元供啟動的同儕表示 ,並分階段進行柔和轉換:
    1. 確保所有客戶並伺服器就能瞭解新的傳輸格式。 我們會繼續使用舊的線路格式。
    2. 啟用新的電線格式,方法是在 交易郵件標頭。 如果雙方都已設定日期,雙方都可以改用新的 線格式。
    3. 柔性轉換效果涵蓋所有層後 她可以使用新的電匯格式。 我們可以移除交易郵件標頭中的位元。
    4. 刪除舊線格式的程式碼,然後保留 交易郵件標頭位元。
  2. 我們可以用特殊方式加上 FIDL 訊息類型和/或介面, [WireFormat=EnvelopeV2] 屬性 (或類似屬性),以指出 訊息/介面應使用新的傳輸格式。
    1. 使用 [WireFormat] 屬性裝飾介面時,似乎 配合線段變更,應該就能比較容易 對結構體執行 WireFormat 變更,因為結構可能是 不同介面中使用的函式,而繫結需要額外的邏輯才能 決定使用結構體的結構定義。
    2. 我們建議介面 [WireFormat] 屬性會影響 介面方法引數的傳輸格式,不含 以遞迴方式影響引數的結構
    3. 即可啟用部分遷移程序,並選擇採用新的電匯格式。 讓團隊按照自己的步調學習
    4. 當所有結構體和介面都擁有 [WireFormat] 屬性時, 可能放置舊線格式,以假設所有結構體和介面會使用 新的傳輸格式,而忽略這個屬性

這兩種軟體轉換方法都需要大量的開發時間 以及容許錯誤 透過實作程式碼來正確執行任一方法、在計畫上執行, 完成後續操作,移除舊程式碼並不容易。

我們可能編寫出程式碼來處理舊版和新的電匯格式 廣告資源否則就無法逐步降落 我們導入新線格式支援的時,請使用 CL。 有鑑於這兩種傳輸格式所需的程式碼都會存在,因此我們建議你 ,您便能使用任一種方法,判斷是否可以進行軟轉換。 如果不是,c'est la vie;最困難的部分

針對軟性轉換或強制轉換,所有執行 FIDL 的 Fuchsia 執行個體 若是以手動方式處理的訊息,你還需要升級成新的傳輸格式。

我們也應該使用這個線路格式,進行其他變更 (例如提議的序數大小變更)。

請注意,此轉換比從 FIDL1 轉換至 FIDL2 簡單許多 而且語言繫結數量十分龐大 由於使用者無法看見任何使用者,因此我們不建議呼叫此 FIDL3 變更4

回溯相容性

建議的有線格式變更是與 API (來源) 相容, 例外狀況:如果我們將 向量/字串元素數量。 為了緩解這種情況,我們可以預先規劃並提取目前的 C 繫結 ,在新傳輸格式降到之前

電匯格式變更與 ABI 不相容,但也有可能需要 ABI 透過實作中所述的策略與現有程式碼的相容性 策略部分。

成效

此 RFC 大幅縮減了信封所需的大小 因此能帶來可觀的整體淨利 然而,整體成效影響並不明顯。 有利於提高效能:

  • 使用可延伸資料結構 (表格與可延伸) 的 FIDL 訊息 會變得更為密集。
  • 針對信封採用統一表示法,也可選擇性使用,可能會減少 因為這可以共用信封程式碼,進而改善快取位置。

不過,請注意以下幾點:

  • 如果可擴充的資料結構因為更優異的表現變得更加普及 所以可能只是因為使用量增加而增加 相較於使用 無法擴充的資料結構
  • 引進所有類型的選用功能,可能會稍微使 FIDL 訊息略微 因為使用者可能會使用這項功能 非選用類型
  • 決定使用信封時,可選的帳號代碼會降低效率 一系列編碼。
  • 非行列程式碼編碼大小 信封,將大小編碼 和處理計數中代表接收端 避免現有行為產生效能迴歸現象

人體工學

  • 您可為所有 FIDL 類型啟用選填屬性。 這是符合人體工學的改進,因為選擇性性變得一致 而不是只用於特定類型
  • 可擴充的資料結構能有效運用在更多 是因為效率很重要,因此使用者不用擔心 並在這裡享有擴充性 都必須使用不可擴充的結構
    • 我們甚至可能會建議 作為 FIDL 資料結構的結構,結構體應保留給 以及高效能的情境
    • 已嘗試擴充的聯集 (RFC-0061) 移除靜態聯集。

說明文件

  • 電線格式說明文件必須更新。
  • 更新說明文件時,您應將信封解釋為 第一級概念:這能提升認知能力 這時讀者遇到 選用性和可擴展資料結構
  • 我們應該更新 FIDL 樣式指南,以在 選用類型應使用 (相較於含有 Sendinel 值的非選用類型)。

安全性

  • 這個 RFC 應該不會對安全性造成重大影響。
  • 不過,我們需要透過雙重標記來調整 內嵌信封格式應經過大幅測試 採用較保守的態度,確保程式碼能妥善處理極端案例。 我們認為使用標準 C/C++ 結構體/聯集來代表 信封 — 相對於手動進行位元改變,遮蓋 - 大幅提升我們對程式碼正確性的信心。

測試

  • 由於這個 RFC 會變更信封的線路格式,因此我們認為 現有 FIDL 測試套件,尤其是相容性測試 - 要充分測試使用信封的所有情境。
  • 我們將新增單元測試,以用於檢查信封、編碼及解碼 離線和內嵌表單,因為這或許是容易出錯的區域。
  • 如果我們同意變更電線格式變更,並視為柔性轉換,請參閱 導入策略一節) 中,新增 測試夥伴後再討論,或許也可能需要改用新的通訊格式。
  • 如果我們同意在這項變更中,公開所有類型的選擇權 我們需要新增任何可選用類型的測試。

缺點、替代方案和未知

  • 只要我們認為提高效率,就能保留現有的線路格式 不等於導入費用。 如果有,我們會建議您採用替代策略 選用規則
  • 針對可擴充的容器使用特殊表示法,並非必要 類型會比使用信封式更有效率。 然而,由於此 RFC 已經存在,我們顯然認為 信封的普通性和統一性 等專業表示法

設計決策

當 RFC 提出建議時,我們也正在積極針對以下決策尋求意見和共識:

  • 詳情請參閱字串和向量一節 如何移動元素數量 (向量) 和位元組數量 (字串) ,這會影響 C 繫結。 我們不採取這種做法,但代價較低:字串和 向量就成為支線, 參照。 (信封還是可以用來指稱外部向量/字串 data.)
  • 我們應該考慮進行軟性轉換或硬轉換?詳情請參閱 實踐策略專區:專業與共 30,000 個
  • 我們建議在 落後信封。 為了進行比較,目前的信封格式使用的是 32/32 位元。 48 位元的尺寸是否合理?
    • 就大小而言,我們可將尺寸編碼最大為 50 位元,只要將 2 位元向右移 2 位元即可 ,因為信封大小一律是 8 的倍數。 (我們無法將三位元向右移動,因為系統無法保證 tag 位元為 0)。 解碼器會向左移動兩個位元來判斷大小。 後面會遺失兩組額外位元,可能用於標記或多個標記。
    • 儘管目前的 64 位元架構通常不允許使用 需要處理 64 位元記憶體空間,通常最多允許 48 位元 部分架構已支援高達 57 位元的位址空間。 詳情請參閱參考資料
    • 16 位元的帳號代碼是否合理?
  • 我們建議使用信封將選用的帳號代碼編碼 無法擴充的容器,比目前的選用功能小 處理編碼 (8 個位元組與 4 個位元組)。
    • 要權衡優缺點較專業的程式碼 請務必找出一致性的原則 我們相信,一致性與統一性比 專門、更精簡的呈現方式,因為選用的控點 相對稀少 (在程式碼中有 37 種可選與 187 個非選用用途)。
  • 是否立即啟用選用性?
    • 因此,我們建議所有類型的選用,在 因為變更可能是 都會以漸進式的方式進行
    • 如要實作這種選用性,就需要變更剖析器。 無論是編碼器、驗證工具和解碼器 因此能提供自己所需的轉換
  • 我們建議使用 32 位元以下的內嵌類型;即可將更多片段
    • 系統可內嵌任何小於 63 位元的資料,因為代碼位元只會使用 1 個 64 位元信封中的位元。
    • 我們可以內嵌小型字串,編碼器-解碼器架構 表示法元素/位元組數量一個位元組 後面加上字串/向量資料。(請參閱前 藝術)。
    • 我們捨棄了這些方法,雖然它更有效率 因為根據內容而非類型 (1) 解碼器無法事先得知預期為內嵌或 是否根據類型變更,以及 (2) 變更 欄位內容代表可以採用不同編碼方式 但似乎與 FIDL 的目標和靜態的重點相似。

既有藝術品和參考資料

作者目前也運用未標記的標記功能,汲取了許多靈感。 指標 動態和功能語言的歷史記錄。 具體來說,Objective-C 64 位元執行階段會大量使用 但使用這些產品和功能 內嵌字串的 5/6 位元編碼)。

由於目前的 64 位元平台一般使用 48 位元 (或更短) 進行編碼 指標後,我們考慮 編碼器與解碼器程式碼的位元間隔,嘗試將 物件的大小與指標。 不過,部分架構已開始擴充實際位址 超過 48 位元 (ARM64x64-64 5 層) 分頁),因此竊取更多指標位元可能不太 永不過時


  1. 信封對所有類型啟用選用功能;不過,在公開排行榜 每個使用者可以視需要單獨處理

  2. 截至 2019 年 1 月 28 日,目前共有 37 個選用控點 Fuchsia 程式碼集。這個數字較保守,因為並不會 計算選用的通訊協定控制代碼,或通訊協定要求控制代碼。 

  3. 這僅適用於無法擴充容器中的信封。 例如結構體和靜態聯集可擴充的容器必須編碼 由於解碼器可能不知道類型, 以便忽略有多少資料 

  4. 但如果要對更多類型開放選用 。