RFC-0048:明確的聯集序數 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 為讓 ABI 對可延伸聯集 (或單工聯集) 造成的影響更加一致,我們提議進行變更,讓其在更接近資料表的範圍內,進行彈性聯集的語法會保持正確,而今天在重新命名聯集或聯集成員時也修正了非常嚴格的 ABI 限制。 |
作者 | |
提交日期 (年/月) | 2019-08-25 |
審查日期 (年/月) | 2019-09-26 |
摘要
為了讓 ABI 對可擴充聯集 (或單純聯集) 產生更一致的影響,我們建議採取下列做法:
- 變更變體成員的語法以要求使用明確序數 (類似於需要資料表序數的方式)。
- 請使用此明確序數,而非先前實作的雜湊序。
- 最後,我們變更有線格式,將聯集序數為 64 位元 (而非 32 位元)。
這些變更可讓彈性聯集的語法更接近資料表,而現在針對重新命名聯集或聯集成員的方面,均已正確修正1 和非常嚴格的 ABI 限制。
動力與設計
除了聯集之外,就類型而言,名稱對於 ABI 沒有任何影響:您可以重新命名列舉、位元、結構和資料表,或者將成員重新命名,而無需擔心二進位檔的相容性。聯集有所不同,因為我們選擇使用以雜湊為基礎的技術來指派變化版本序數 (請參閱 RFC-0061:可擴充的節點)。
Google 發現這個簡稱,並已提議解決這項問題:請參閱「意圖實作:xunion ordinals 變更」一文,其中建議變更雜湊配置,使其只包含成員名稱。
相反地,本提案會進一步運用明確的序數,避免名稱與 ABI 相容性之間有任何關聯。我們認為,在聯集宣告中編寫序數需要多一點工夫:資料表至今沒有明確的序數沒有問題,而其他熱門 IDL 成員或變數的編號也已大幅增加。
此外,為了進一步與資料表對齊,我們要求序數從 1 依序指派,並允許使用關鍵字 reserved
明確略過聯集變化版本。
僅針對通訊協定進行雜湊處理
與類型不同,通訊協定是使用以雜湊為基礎的方法指派序數。這麼做是為了達成以下兩個主要用途:
- 通訊協定可以組合,因此我們需要全域分派配置,以避免距離問題發生中斷。請參閱 [RFC-0063:OrdinalRange、RFC-0020: Interface Ordinal Hashing 和 RFC-0029:遞增方法序數。
- 實際上,全域唯一識別碼可以大幅簡化並強化監控和追蹤等類似需求,例如需要能明確識別方法叫用的 fidlcat。
這類使用案例不會轉譯為類型。
本提案的影響是僅用於通訊協定。只有一種雜湊配置,也就是 RFC-0029 中所述。
64 位元序數是標準的
目前,聯集內嵌內容有 4 個位元組的邊框間距:
- 序數 (
uint32
) - 邊框間距 (
uint32
) - 信封 (16 個位元組)
相反地,我們希望在格式中明確呼叫所有位元組,進而將序數變更為 64b。一般而言,我們偏好無邊框的結構,因為這類結構較有效率 (例如,不需要明確的網路迷集或額外的程式設計表)。
請參閱「實作策略」一節,瞭解如何將自己轉換成 64 位元序數。
JSON 線格式
我們之前已討論過,當我們建立 JSON 傳輸格式時,重新命名類型和成員時,會對該格式產生 ABI 的影響。
建議您依「線路」格式區分 ABI 故障情形。我們可以透過不同屬性取得不同的屬性。極少數訊息需要與 ABI 相容所有支援的可能傳輸格式,在改進方式上將非常有限。有些客戶應盡可能使用更彈性的規則。
預做準備:稀疏資料表
目前我們已討論支援稀疏資料表,例如除了結構和資料表外,還有第三個版面配置和類似記錄的資料。如果我們決定導入這個第三個選項,就會遵循本提案和目前資料表的語法:
sparse_table Example {
1: T1 field1;
2: reserved; // deprecated
3: T3 field3;
};
導入策略
如要啟用柔性轉換,我們必須區分傳統 (32 位元雜湊) 序數和建議的 (64 位元明確) 序數語法。做法如下:
- 在 fidlc 中新增檢查,確保 32 位元雜湊序數的值絕不會低於 N。舉例來說,如果 N 是 512,則雜湊序數的十六進位值至少必須為 0x200。
- 如果雜湊序數小於 0x200,將導致編譯錯誤,且必須使用
[Selector=]
屬性手動重新命名欄位名稱。我們會先將[Selector]
新增至適當欄位,再以 fidlc 套用這項變更。 - 由於現有雜湊配置是隨機的,我們預期雜湊錯誤幾乎發生於零次,因此您可能不需要手動解決。
- 新增這項檢查可有效將
[0..N]
序數空間分配給明確的序數,並確保該方法不會與雜湊序數衝突。
- 如果雜湊序數小於 0x200,將導致編譯錯誤,且必須使用
- 當語言繫結解讀序數時:
- 如果序數介於
[0, N)
之間,則序數為 64 位元且明確。 - 如果序數介於
[N, UINT32_MAX]
之間,則序數為 32 位元並經過雜湊處理。 - 如果序數介於
[UINT32_MAX, UINT64_MAX)
之間,繫結「必須」叫用錯誤,並關閉管道,加上 Epitaph。
- 如果序數介於
人體工學
讓 ABI 人體工學變得更簡單,大幅減少具有明確序數的語法成本。
說明文件與範例
至少:
回溯相容性
未採用明確序數語法定義的聯集將繼續使用現有的 32 位元雜湊普通配置。因此,現今的聯集將繼續與 API 和 ABI 相容。
以明確序數語法定義的聯集將使用此 RFC 中所述的 64 位元序數配置。如要瞭解如何同時支援 32 位元和 64 位元序數配置,請參閱「實作策略」一節。
效能
極度微幅的改善:這個配置比雜湊序數的效率更好,因為 Switch() 陳述式的程式碼產生器較佳。
安全性
沒有影響。
測試
和平常一樣焦頭。
缺點、替代方案和未知
替代方法:僅限成員名稱的序數雜湊
請參閱「意圖實作:xunion ordinals change」。
經過進一步思考,我們認為上述做法不夠充足,因為語法優勢 (來源中沒有序數) 無法獲得補償:
- 難以瞭解 ABI 影響的兩種雜湊配置;
- 在重新命名宣告或成員時,讓聯集與同層級列舉、位元、結構和資料表有所不同。
先前的圖片和參考資料
沒有特別相關。
Footnote1
本文件中的「聯合」是指可擴充的聯集,而非生命週期終止附近的「靜態」聯集。
Footnote3
From: apang@google.com
收件者:fidl 使用者名單
日期:2019 年 5 月 23 日
FIDLers,你好!昨天編寫測試時,FIDL 團隊發現以目前的 Xunion 規格和植入式程式碼,出現了意想不到的行為。若其中一個宣告:
xunion MyXUnion {
int32 i; // ordinal might be 0x11111111
}
````
and renames the name of the xunion (not the field), the ordinal of the field
changes:
```fidl
// rename from MyXUnion to MyXUnion2
xunion MyXUnion2 {
int32 i; // ordinal now changes to 0x22222222 since the xunion was renamed. d'oh!
}
這是預料之外的行為:變更 xunion 的名稱不應變更 ABI。
要在這個方面做得更好:
- 我們想要修改 xunion RFC (RFC-0061),確保序數只衍生自欄位名稱,並移除一般雜湊計算中的 xunion 名稱和程式庫名稱。
- 幸好,我們必須變更程式碼,這意味著 xunion ABI 的變更,可能導致建構作業不佳。幸好,我們可以採用 Jeremy Manson 為方法實作序數雜湊的先進技術,讓這項作業能夠進行柔軟的轉換:讓用戶端一併檢查新舊雜湊,直到變更在樹狀結構中完全套用變更為止。
(其中一堂課會學到:未來我們應仔細研究序數雜湊包含的內容,以及是否應變更這些元素是否應改變 ABI)。
我們相信這個是低風險的計畫,因為可以進行柔性轉換,而 Jeremy 成功完成方法序對。煩請留言告知我們,否則我們會盡快開始處理。
-
某種程度上,名稱對於訊息的二進位傳輸格式 (即位元、列舉、結構、資料表) 和聯集沒有任何影響。因此與其他同類應用程式的差異 ↩