[英]Is there a portable Binary-serialisation schema in FlatBuffers/Protobuf that supports arbitrary 24bit signed integer definitions?
我們以高數據速率通過 UART 串行發送數據,因此數據大小很重要。 對於我們的數據,最優化的格式是 Int24,它可以簡化為 C/C++ 下的 C 位域結構(GCC 編譯器)以實現完美優化:
#pragma pack(push, 1)
struct Int24
{
int32_t value : 24;
};
#pragma pack(pop)
typedef std::array<Int24,32> ArrayOfInt24;
這些數據與其他數據打包在一起,並在設備和雲基礎設施之間共享。 基本上,我們需要在不同架構和編程語言的設備之間發送二進制序列化。 我們希望使用基於模式的二進制序列化,例如 ProtoBuffers 或 FlatBuffers,以避免客戶端代碼需要自行處理二進制補碼符號位處理的相應位移和恢復。 即在非 C 語言中讀取 24 位值需要以下內容:
bool isSigned = (_b2 & (byte)0x80) != 0; // Sign extend negative quantities
int32_t value = _b0 | (_b1 << 8) | (_b2 << 16) | (isSigned ? 0xFF : 0x00) << 24;
如果尚不存在哪個(如果有)現有的二進制序列化庫可以輕松修改以擴展對此的支持,因為我們願意在這方面添加到任何開源項目中。
根據不同的情況,您可能想查看 ASN.1 和未對齊的打包編碼規則 (uPER)。 這是一種廣泛用於電話的二進制序列化,可輕松減少傳輸的位數。 工具可用於 C、C++、C#、Java、Python(我認為它們涵蓋了 uPER)。 一個好的起點是有用的舊技術。
您可能選擇使用它的原因之一是 uPER 最終可能比其他任何東西都做得更好。 其他好處是限制(關於值和數組大小)。 您可以在您的架構中表達這些,生成的代碼將根據它們檢查數據。 這可以對項目產生真正的影響 - 自動清理傳入數據是抵御攻擊的好方法 - 而 GPB 不會這樣做。
不使用它的原因是最好的工具是商業的,而且價格昂貴。 雖然有一些開源工具非常好,但不一定實現整個 ASN.1 標准(這是很大的)。 這也是一個學習曲線,盡管(在基本層面上)與 Google Protocol Buffers 並沒有太大的不同。 事實上,在谷歌宣布 GPB 的大會上,有人問“為什么不使用 ASN.1?”。 Google 的團隊沒有聽說過它。 有點諷刺的是,一家搜索公司沒有在網上搜索二進制序列化技術,而是直接發明了他們自己的......
protobuf 的 varint 格式的一個特別有效的用途是將其用作一種壓縮方案,通過寫入值之間的增量。
在您的情況下,如果連續值之間存在任何相關性,您可能會有一個repeated sint32 values
字段。 然后作為數組中的第一個條目,寫入第一個值。 對於所有其他條目,請寫出與先前值的差值。
這樣,例如[100001, 100050, 100023, 95000]
將被編碼為[100001, 49, -27, -5023]
。 作為打包的 varint 數組,增量將占用 3、1、1 和 2 個字節,總共 7 個字節。 與占用 12 個字節的固定 24 位編碼或占用 12 個字節的非增量 varint 相比。
當然這也需要接收端的一些代碼來處理。 但是將先前的值相加很容易以任何語言實現。
FlatBuffers 不支持 24 位整數。 表示它的唯一方法是:
struct Int24 { a:ubyte; b:ubyte; c:ubyte; }
這顯然不會為您進行位移,但仍然允許您將多個Int24
有效地打包在父向量或結構中。 當存儲在表中時,它還可以節省一個字節,盡管只有 32 位 int 可能會更好,因為開銷更高。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.