偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

深入淺出 FlatBuffers 原理

開發(fā)
FlatBuffers 是一個(gè)開源的、跨平臺(tái)的、高效的、提供了多種語言接口的序列化工具庫。實(shí)現(xiàn)了與 Protocal Buffers 類似的序列化格式。主要由 Wouter van Oortmerssen 編寫,并由 Google 開源。Oortmerssen 最初為 Android 游戲和注重性能的應(yīng)用而開發(fā)了 FlatBuffers,現(xiàn)在它具有 C ++、C#、C、Go、Java、PHP、Python 和 JavaScript 的接口。

 [[412244]]

一 前言

FlatBuffers 是一個(gè)開源的、跨平臺(tái)的、高效的、提供了多種語言接口的序列化工具庫。實(shí)現(xiàn)了與 Protocal Buffers 類似的序列化格式。主要由 Wouter van Oortmerssen 編寫,并由 Google 開源。Oortmerssen 最初為 Android 游戲和注重性能的應(yīng)用而開發(fā)了 FlatBuffers,現(xiàn)在它具有 C ++、C#、C、Go、Java、PHP、Python 和 JavaScript 的接口。

高德地圖數(shù)據(jù)編譯增量發(fā)布使用了FlatBuffers序列化工具,借此契機(jī)對(duì)FlatBuffers原理進(jìn)行研究并分享于此。本文簡單介紹 FlatBuffers Scheme,通過剖析 FlatBuffers 序列化與反序列化原理,重點(diǎn)回答以下問題:

問題1:FlatBuffers 如何做到反序列化速度極快的(或者說無需解碼)。
問題2:FlatBuffers 如何做到默認(rèn)值不占存儲(chǔ)空間的(Table 結(jié)構(gòu)內(nèi)的變量)。
問題3:FlatBuffers 如何做到字節(jié)對(duì)齊的。
問題4:FlatBuffers 如何做到向前向后兼容的(Struct 結(jié)構(gòu)除外)。
問題5:FlatBuffers 在 add 字段時(shí)有沒有順序要求(Table 結(jié)構(gòu))。
問題6:FlatBuffers 如何根據(jù) Scheme 自動(dòng)生成編解碼器。
問題7:FlatBuffers 如何根據(jù) Scheme 自動(dòng)生成 Json。

二 FlatBuffers Scheme

FlatBuffers 通過 Scheme 文件定義數(shù)據(jù)結(jié)構(gòu),Schema 定義與其他框架使用的IDL(Interface description language)語言類似簡單易懂,F(xiàn)latBuffers 的 Scheme 是一種類 C 的語言(盡管 FlatBuffers 有自己的接口定義語言 Scheme 來定義要與之序列化的數(shù)據(jù),但它也支持 Protocol Buffers 中的 .proto 格式)。下面以官方 Tutorial 中的 monster.fbs 為例進(jìn)行說明:

// Example IDL file for our monster's schema.namespace MyGame.Sample;enum Color:byte { Red = 0, Green, Blue = 2 }union Equipment { Weapon } // Optionally add more tables.struct Vec3 { x:float; y:float; z:float;}table Monster { pos:Vec3; mana:short = 150; hp:short = 100; name:string; friendly:bool = false (deprecated); inventory:[ubyte]; color:Color = Blue; weapons:[Weapon]; equipped:Equipment; path:[Vec3];}table Weapon { name:string; damage:short;}root_type Monster;
namespace MyGame.Sample;

namespace 定義命名空間,可以定義嵌套的命名空間,用 . 分割。

enum Color:byte { Red = 0, Green, Blue = 2 };

enum 定義枚舉類型。和常規(guī)的枚舉類稍有不同的地方是可以定義類型。比如這里的 Color 是 byte 類型。enum 字段只能新增,不能廢棄。

union Equipment {Weapon} // Optionally add more tables

union 類似 C/C++ 中的概念,一個(gè) union 中可以放置多種類型,共同使用一個(gè)內(nèi)存區(qū)域。這里的使用是互斥的,即這塊內(nèi)存區(qū)域只能由其中一種類型使用。相對(duì) struct 來說比較節(jié)省內(nèi)存。union 跟 enum 比較類似,但是 union 包含的是 table,enum 包含的是 scalar 或者 struct。union 也只能作為 table 的一部分,不能作 root type。

struct Vect3{ x : float; y : float; z : float;};

struct 所有字段都是必填的,因此沒有默認(rèn)值。字段也不能添加或者廢棄,且只能包含標(biāo)量或者其他 struct。struct 主要用于數(shù)據(jù)結(jié)構(gòu)不會(huì)發(fā)生改變的場(chǎng)景,相對(duì) table 使用更少的內(nèi)存,lookup 的時(shí)候速度更快(struct 保存在父 table 中,不需要使用 vtable)。

table Monster{};

table 是在 FlatBuffers 中定義對(duì)象的主要方式,由一個(gè)名稱(這里是 Monster)和一個(gè)字段列表組成??梢园厦娑x的所有類型。每個(gè)字段(Field)包括名稱、類型和默認(rèn)值三部分;每個(gè)字段都有默認(rèn)值,如果沒有明確寫出則默認(rèn)為 0 或者 null。每個(gè)字段都不是必須的,可以為每個(gè)對(duì)象選擇要省略的字段,這是 FlatBuffers 向前和向后兼容的機(jī)制。

root_type Monster;

用于指定序列化后的數(shù)據(jù)的 root table。

Scheme 設(shè)計(jì)需要特別注意的:

新字段只能加在 table 的后面。舊代碼會(huì)忽略這個(gè)字段,仍然可以正常執(zhí)行。新代碼讀取舊的數(shù)據(jù),會(huì)取到新增字段的默認(rèn)值。
即使字段不再使用了也不能從 Scheme 中刪除。可以標(biāo)記為 deprecated,在生成代碼的時(shí)候不會(huì)生成該字段的訪問器。
如果需要嵌套的 vector,可以將 vector 包裝在 table 中。string 對(duì)于其他編碼可以使用 [byte] 或者 [ubyte] 支持。

三 FlatBuffers 的序列化

簡單來說 FlatBuffers 就是把對(duì)象數(shù)據(jù),保存在一個(gè)一維的數(shù)組中,將數(shù)據(jù)都緩存在一個(gè) ByteBuffer 中,每個(gè)對(duì)象在數(shù)組中被分為兩部分。元數(shù)據(jù)部分:負(fù)責(zé)存放索引。真實(shí)數(shù)據(jù)部分:存放實(shí)際的值。然而 FlatBuffers 與大多數(shù)內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)不同,它使用嚴(yán)格的對(duì)齊規(guī)則和字節(jié)順序來確保 buffer 是跨平臺(tái)的。此外,對(duì)于 table 對(duì)象,F(xiàn)latBuffers 提供前向/后向兼容性和 optional 字段,以支持大多數(shù)格式的演變。除了解析效率以外,二進(jìn)制格式還帶來了另一個(gè)優(yōu)勢(shì),數(shù)據(jù)的二進(jìn)制表示通常更具有效率。我們可以使用 4 字節(jié)的 UInt 而不是 10 個(gè)字符來存儲(chǔ) 10 位數(shù)字的整數(shù)。

FlatBuffers 對(duì)序列化基本使用原則:

小端模式。FlatBuffers 對(duì)各種基本數(shù)據(jù)的存儲(chǔ)都是按照小端模式來進(jìn)行的,因?yàn)檫@種模式目前和大部分處理器的存儲(chǔ)模式是一致的,可以加快數(shù)據(jù)讀寫的數(shù)據(jù)。
寫入數(shù)據(jù)方向和讀取數(shù)據(jù)方向不同。

FlatBuffers 向 ByteBuffer 中寫入數(shù)據(jù)的順序是從 ByteBuffer 的尾部向頭部填充,由于這種增長方向和 ByteBuffer 默認(rèn)的增長方向不同,因此 FlatBuffers 在向 ByteBuffer 中寫入數(shù)據(jù)的時(shí)候就不能依賴 ByteBuffer 的 position 來標(biāo)記有效數(shù)據(jù)位置,而是自己維護(hù)了一個(gè) space 變量來指明有效數(shù)據(jù)的位置,在分析 FlatBuffersBuilder 的時(shí)候要特別注意這個(gè)變量的增長特點(diǎn)。但是,和數(shù)據(jù)的寫入方向不同的是,F(xiàn)latBuffers 從 ByteBuffer 中解析數(shù)據(jù)的時(shí)候又是按照 ByteBuffer 正常的順序來進(jìn)行的。FlatBuffers 這樣組織數(shù)據(jù)存儲(chǔ)的好處是,在從左到右解析數(shù)據(jù)的時(shí)候,能夠保證最先讀取到的就是整個(gè) ByteBuffer 的概要信息(例如 Table 類型的 vtable 字段),方便解析。

對(duì)于每種數(shù)據(jù)類型的序列化:

1 標(biāo)量類型

標(biāo)量類型即基本類型,如:int,double,bool等,標(biāo)量類型使用直接尋址進(jìn)行數(shù)據(jù)訪問。

示例:short mana = 150; 12個(gè)字節(jié),存儲(chǔ)結(jié)構(gòu)如下:

schema 中定義標(biāo)量可以設(shè)置默認(rèn)值。文章最初提到 FlatBuffers 的默認(rèn)值不占存儲(chǔ)空間的,對(duì)于 table 內(nèi)部的標(biāo)量,是可以做到默認(rèn)值不存儲(chǔ)的,如果變量的值不需要改變,該字段在 vtable 中對(duì)應(yīng)的 offset 的值設(shè)置為 0 即可,默認(rèn)值被記錄在解碼接口內(nèi),解碼時(shí)獲取該字段的 offset 為 0 時(shí),解碼接口則返回默認(rèn)值。對(duì)于 struct 結(jié)構(gòu)因?yàn)闆]有使用 vtable 結(jié)構(gòu),因此內(nèi)部的標(biāo)量沒有默認(rèn)值,必須存儲(chǔ)(struct 類型和 table 類型的序列化原理在下文會(huì)詳細(xì)說明)。

  1. // Computes how many bytes you'd have to pad to be able to write an// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in// memory).inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {    return ((~buf_size) + 1) & (scalar_size - 1);} 

標(biāo)量數(shù)據(jù)類型是按其本身字節(jié)數(shù)大小進(jìn)行對(duì)齊。通過 PaddingBytes 函數(shù)計(jì)算,所有標(biāo)量都會(huì)調(diào)用這個(gè)函數(shù),進(jìn)行字節(jié)對(duì)齊。

2 Struct 類型

除了基本類型之外,F(xiàn)latBuffers 中只有 Struct 類型使用直接尋址進(jìn)行數(shù)據(jù)訪問。FlatBuffers 規(guī)定 Struct 類型用于存儲(chǔ)那些約定成俗、永不改變的數(shù)據(jù),這種類型的數(shù)據(jù)結(jié)構(gòu)一旦確定便永遠(yuǎn)不會(huì)改變,沒有任何字段是可選的(也沒有默認(rèn)值),字段可能不會(huì)被添加或被棄用,所以 structs 不提供前向/后向兼容性。在這個(gè)規(guī)定之下,為了提高數(shù)據(jù)訪問速度,F(xiàn)latBuffers 單獨(dú)對(duì) Struct 使用了直接尋址的方式。字段的順序即為存儲(chǔ)的順序。struct 有的特性一般不作為 schema 文件的根。

示例:struct Vec3(16, 17, 18); 12個(gè)字節(jié)

struct 定義了一個(gè)固定的內(nèi)存布局,其中所有字段都與其大小對(duì)齊,并且 struct 與其最大標(biāo)量成員對(duì)齊。

3 vector 類型

vector 類型實(shí)際上就是 schema 中聲明的數(shù)組類型,F(xiàn)latBuffers 中也沒有單獨(dú)的類型和它對(duì)應(yīng),但是它卻有自己獨(dú)立的一套存儲(chǔ)結(jié)構(gòu),在序列化數(shù)據(jù)時(shí)先會(huì)從高位到低位依次存儲(chǔ) vector 內(nèi)部的數(shù)據(jù),然后再在數(shù)據(jù)序列化完畢后寫入 Vector 的成員個(gè)數(shù)。數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)如下:

示例:byte[] treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

vector size 的類型為 int,因此在初始化申請(qǐng)內(nèi)存時(shí) vector 進(jìn)行四字節(jié)字節(jié)對(duì)齊。

4 String 類型

FlatBuffers 字符串按照 utf-8 的方式進(jìn)行了編碼,在實(shí)現(xiàn)字符串寫入的時(shí)候?qū)⒆址木幋a數(shù)組當(dāng)做了一維的 vector 來實(shí)現(xiàn)。string 本質(zhì)上也可以看做是 byte 的 vector ,因此創(chuàng)建過程和 vector 基本一致,唯一的區(qū)別就是字符串是以null結(jié)尾,即最后一位是 0。string 寫入數(shù)據(jù)的結(jié)構(gòu)如下:

示例:string name = “Sword”;

vector size 的類型為 int,因此在初始化申請(qǐng)內(nèi)存時(shí)字符串進(jìn)行四字節(jié)字節(jié)對(duì)齊。

5 Union 類型

Union 類型比較特殊,F(xiàn)latBuffers 規(guī)定這個(gè)類型在使用上具有如下兩個(gè)限制:

Union 類型的成員只能是 Table 類型。
Union 類型不能是一個(gè) schema 文件的根。
FlatBuffers 中沒有特定類型表示 union,而是會(huì)生成一個(gè)單獨(dú)的類對(duì)應(yīng) union 的成員類型。與其他類型的主要區(qū)別是需要先指定類型,在序列化 Union 的時(shí)候一般先寫入 Union 的 type,然后再寫入 Union 的數(shù)據(jù)偏移;在反序列化 Union 的時(shí)候一般先
析出 Union 的 type,然后再按照 type 對(duì)應(yīng)的 Table 類型來解析 Union 對(duì)應(yīng)的數(shù)據(jù)。

6 Enum 類型

FlatBuffers 中的 enum 類型在數(shù)據(jù)存儲(chǔ)的時(shí)候是和 byte 類型存儲(chǔ)的方式一樣的。因?yàn)楹?Union 類型相似,enum 類型在 FlatBuffers 中也沒有單獨(dú)的類與它對(duì)應(yīng),在 schema 中聲明為 enum 的類會(huì)被編譯生成單獨(dú)的類。

enum 類型不能是一個(gè) schema 文件的根。

7 Table 類型

table 是 FlatBuffers 的基石,為了解決數(shù)據(jù)結(jié)構(gòu)變更的問題,table 通過 vtable 間接訪問字段。每個(gè) table 都帶有一個(gè) vtable(可以在具有相同布局的多個(gè) table 之間共享),并且包含存儲(chǔ)此特定類型 vtable 實(shí)例的字段的信息。vtable 還可能表明該字段不存在(因?yàn)榇?FlatBuffers 是使用舊版本的代碼編寫的,僅僅因?yàn)樾畔?duì)于此實(shí)例不是必需的,或者被視為已棄用),在這種情況下會(huì)返回默認(rèn)值。

table 的內(nèi)存開銷很小(因?yàn)?vtables 很小并且共享)訪問成本也很?。ㄩg接訪問),但是提供了很大的靈活性。table 在特殊情況下可能比等價(jià)的 struct 花費(fèi)更少的內(nèi)存,因?yàn)樽侄卧诘扔谀J(rèn)值時(shí)不需要存儲(chǔ)在 buffer 中。這樣的結(jié)構(gòu)決定了一些復(fù)雜類型的成員都是使用相對(duì)尋址進(jìn)行數(shù)據(jù)訪問的,即先從Table 中取到成員常量的偏移,然后根據(jù)這個(gè)偏移再去常量真正存儲(chǔ)的地址去取真實(shí)數(shù)據(jù)。

單就結(jié)構(gòu)來講:首先可以將 Table 分為兩個(gè)部分,第一部分是存儲(chǔ) Table 中各個(gè)成員變量的概要,這里命名為 vtable,第二部分是 Table 的數(shù)據(jù)部分,存儲(chǔ) Table 中各個(gè)成員的值,這里命名為 table_data。注意 Table 中的成員如果是簡單類型或者 Struct 類型,那么這個(gè)成員的具體數(shù)值就直接存儲(chǔ)在 table_data中;如果成員是復(fù)雜類型,那么 table_data 中存儲(chǔ)的只是這個(gè)成員數(shù)據(jù)相對(duì)于寫入地址的偏移,也就是說要獲得這個(gè)成員的真正數(shù)據(jù)還要取出 table_data 中的數(shù)據(jù)進(jìn)行一次相對(duì)尋址。

vtable 是一個(gè) short 類型的數(shù)組,其長度為(字段個(gè)數(shù)+2)*2字節(jié),第一個(gè)字段是 vtable 的大小,包括這個(gè)大小本身;第二個(gè)字段是 vtable 對(duì)應(yīng)的對(duì)象的大小,包括到 vtable 的 offset;接下來是每個(gè)字段相對(duì)于對(duì)象開始位置的 offset。
table_data 的開頭是 vtable 開始位置減去當(dāng)前table對(duì)象開始位置的 INT 型 offset,由于 vtable 可能在任意的地方,這個(gè)值有可能是負(fù)值。table_data開始用int存儲(chǔ)了vtable的offset,因此進(jìn)行了四字節(jié)對(duì)齊的。
add 的操作是添加 table_data,由于 Table 數(shù)據(jù)結(jié)構(gòu)的是通過 vtable - table_data 機(jī)制存儲(chǔ)的,這個(gè)操作沒有強(qiáng)制要求字段的先后順序,對(duì)順序沒有要求,因?yàn)関table在記錄每個(gè)字段相對(duì)于對(duì)象開始位置的 offset 時(shí)是按照 schema 中定義的順序進(jìn)行存儲(chǔ)的,所以在add字段的時(shí)候即使沒有順序也可以根據(jù) offset 獲取正確的值。需要注意的是,每次add字段時(shí) FlatBuffers 都會(huì)做字節(jié)對(duì)齊處理。

  1. std::string e_poiId = "1234567890";double e_coord_x = 0.1double e_coord_y = 0.2;int e_minZoom = 10;int e_maxZoom = 200;//addfeatureBuilder.add_poiId(nameData);featureBuilder.add_x(e_coord_x);featureBuilder.add_y(e_coord_y);featureBuilder.add_maxZoom(e_maxZoom);featureBuilder.add_minZoom(e_minZoom);auto rootData = featurePoiBuilder.Finish();flatBufferBuilder.Finish(rootData);blob = flatBufferBuilder.GetBufferPointer();blobSize = flatBufferBuilder.GetSize(); 

add 順序 1:最終二進(jìn)制的大小為 72 字節(jié)。

  1. std::string e_poiId = "1234567890";double e_coord_x = 0.1double e_coord_y = 0.2;int e_minZoom = 10;int e_maxZoom = 200;//addfeatureBuilder.add_poiId(nameData);featureBuilder.add_x(e_coord_x);featureBuilder.add_minZoom(e_minZoom);featureBuilder.add_y(e_coord_y);featureBuilder.add_maxZoom(e_maxZoom);auto rootData = featurePoiBuilder.Finish();flatBufferBuilder.Finish(rootData);blob = flatBufferBuilder.GetBufferPointer();blobSize = flatBufferBuilder.GetSize(); 

add 順序 2:最終二進(jìn)制的大小為 80 字節(jié)。

add 順序 1 和 add 順序 2 對(duì)應(yīng)的 schema 文件一樣,表達(dá)的數(shù)據(jù)也一樣,Table 結(jié)構(gòu)在 add 字段時(shí)有沒有順序要求。序列化后的數(shù)據(jù)大小差8個(gè)字節(jié),原因就是字節(jié)對(duì)齊導(dǎo)致的。因此 add 字段的時(shí)候,盡量把相同類型的字段放在一起進(jìn)行 add,這樣會(huì)避免不必要的字節(jié)對(duì)齊,獲取更小的序列化結(jié)果。

FlatBuffers 的向前向后兼容指的是 table 結(jié)構(gòu)。table 結(jié)構(gòu)每個(gè)字段都有默認(rèn)值,如果沒有明確寫出則默認(rèn)為 0 或者 null。每個(gè)字段都不是必須的,可以為每個(gè)對(duì)象選擇要省略的字段,這是 FlatBuffers 向前和向后兼容的機(jī)制。需要注意的是:

新的字段只能加在 table 的后面。舊的代碼會(huì)忽略這個(gè)字段,仍然可以正常執(zhí)行。新的代碼讀取舊的數(shù)據(jù),新增的字段會(huì)返回默認(rèn)值。
即使字段不再使用了也不能從 schema 中刪除。可以標(biāo)記為 deprecated,在生成代碼的時(shí)候該字段不會(huì)生成該字段的接口。

四 FlatBuffers 的反序列化

FlatBuffers 反序列化的過程就很簡單了。由于序列化的時(shí)候保存好了各個(gè)字段的 offset,反序列化的過程其實(shí)就是把數(shù)據(jù)從指定的 offset 中讀取出來。反序列化的過程是把二進(jìn)制流從 root table 往后讀。從 vtable 中讀取對(duì)應(yīng)的 offset,然后在對(duì)應(yīng)的 object 中找到對(duì)應(yīng)的字段,如果是引用類型,string / vector / table,讀取出 offset,再次尋找 offset 對(duì)應(yīng)的值,讀取出來。如果是非引用類型,根據(jù) vtable 中的 offset ,找到對(duì)應(yīng)的位置直接讀取即可。對(duì)于標(biāo)量,分 2 種情況,默認(rèn)值和非默認(rèn)值。默認(rèn)值的字段,在讀取的時(shí)候,會(huì)直接從 flatc 編譯后的文件中記錄的默認(rèn)值中讀取出來。非默認(rèn)值字段,二進(jìn)制流中就會(huì)記錄該字段的 offset,值也會(huì)存儲(chǔ)在二進(jìn)制流中,反序列化時(shí)直接根據(jù)offset讀取字段值即可。

整個(gè)反序列化的過程零拷貝,不消耗占用任何內(nèi)存資源。并且 FlatBuffers 可以讀取任意字段,而不是像 Json 和 protocol buffer 需要讀取整個(gè)對(duì)象以后才能獲取某個(gè)字段。FlatBuffers 的主要優(yōu)勢(shì)就在反序列化這里了。所以 FlatBuffers 可以做到解碼速度極快,或者說無需解碼直接讀取。

五 FlatBuffers 的自動(dòng)化

FlatBuffers 的自動(dòng)化包括自動(dòng)生成編碼解碼接口和自動(dòng)生成 Json,自動(dòng)化生成編解碼接口和自動(dòng)生成 Json,都依賴 schem 的解析。

1 schema 描述文件解析

FlatBuffers 描述文件解析器按游標(biāo)的方式順序進(jìn)行識(shí)別 FlatBuffers 支持的數(shù)據(jù)結(jié)構(gòu)。獲取字段名稱、字段類型、字段默認(rèn)值、是否棄用等屬性。支持關(guān)鍵字:標(biāo)量類型、非標(biāo)量類型、include、namespace、root_type。

如果需要嵌套的vector,可以將vector包裝在table中。

2 自動(dòng)生成編碼解碼接口

FlatBuffers 使用模板編程,編碼解碼接口僅生成h文件。實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)的定義,并特化出變量的Add函數(shù)、Get函數(shù),校驗(yàn)函數(shù)接口。對(duì)應(yīng)的文件名為filename_generated.h。

3 自動(dòng)生成Json

FlatBuffers 的主要目標(biāo)是避免反序列化。通過定義二進(jìn)制數(shù)據(jù)協(xié)議來實(shí)現(xiàn)的,一種將定義好的將數(shù)據(jù)轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)的方法。由該協(xié)議創(chuàng)建的二進(jìn)制結(jié)構(gòu)無需進(jìn)一步解碼即可讀取。因此在自動(dòng)生成json時(shí),只需要提供二進(jìn)制數(shù)據(jù)流和二進(jìn)制定義結(jié)構(gòu)就可以讀物數(shù)據(jù),轉(zhuǎn)換成json。

Json結(jié)構(gòu)與 FlatBuffers 結(jié)構(gòu)保持一致。
默認(rèn)值不輸出 Json。

六 FlatBuffers 的優(yōu)缺點(diǎn)

FlatBuffers 通過 Scheme 文件定義數(shù)據(jù)結(jié)構(gòu),Schema 定義與其他框架使用的IDL(Interface description language)語言類似簡單易懂,F(xiàn)latBuffers 的 Scheme 是一種類C的語言(盡管 FlatBuffers 有自己的接口定義語言Scheme來定義要與之序列化的數(shù)據(jù),但它也支持 Protocol Buffers 中的 .proto 格式)。下面以官方 Tutorial 中的 monster.fbs 為例進(jìn)行說明:

1 優(yōu)點(diǎn)

解碼速度極快,將序列化數(shù)據(jù)存儲(chǔ)在緩存中,這些數(shù)據(jù)既可以寫出至文件中,又可以通過網(wǎng)絡(luò)原樣傳輸,也可直接讀取而沒有任何解析開銷,訪問數(shù)據(jù)時(shí)的唯一內(nèi)存需求就是緩沖區(qū),不需要額外的內(nèi)存分配。
擴(kuò)展性、靈活性:它支持的可選字段意味著具有很好的前向/后向兼容。FlatBuffers 支持選擇性地寫入數(shù)據(jù)成員,這不僅為某一個(gè)數(shù)據(jù)結(jié)構(gòu)在應(yīng)用的不同版本之間提供了兼容性,同時(shí)還能使程序員靈活地選擇是否寫入某些字段及靈活地設(shè)計(jì)傳輸?shù)臄?shù)據(jù)結(jié)構(gòu)。
跨平臺(tái):支持 C++11、Java,而不需要任何依賴庫,在最新的 gcc、clang、vs2010 等編輯器上也工作良好。使用簡單方便 ,僅僅需要自動(dòng)生成的少量代碼和一個(gè)單一的頭文件依賴,很容易集成到現(xiàn)有系統(tǒng)中,生成的 C++ 代碼提供了簡單的訪問和構(gòu)造接口,可以兼容 Json 等其他格式的解析。

2 缺點(diǎn)

數(shù)據(jù)無可讀性,必須進(jìn)行數(shù)據(jù)可視化才能理解數(shù)據(jù)。
向后兼容性局限,在 schema 中添加或刪除字段必須小心。

七 總結(jié)

相比其它的序列化工具,F(xiàn)latBuffers 最大的優(yōu)勢(shì)是反序列化速度極快,或者說無需解碼。如果使用場(chǎng)景是需要經(jīng)常解碼序列化的數(shù)據(jù),則有可能從 FlatBuffers 的特性獲得一定的好處。

責(zé)任編輯:梁菲 來源: 阿里云云棲號(hào)
相關(guān)推薦

2021-03-16 08:54:35

AQSAbstractQueJava

2018-12-25 08:00:00

2022-02-25 08:54:50

setState異步React

2011-07-04 10:39:57

Web

2012-05-21 10:06:26

FrameworkCocoa

2017-07-02 18:04:53

塊加密算法AES算法

2019-01-07 15:29:07

HadoopYarn架構(gòu)調(diào)度器

2021-08-10 14:10:02

Nodejs后端開發(fā)

2020-11-06 09:24:09

node

2022-09-26 09:01:15

語言數(shù)據(jù)JavaScript

2022-05-06 07:19:11

DOMDiff算法

2019-11-21 09:16:14

OpenStack安全組MAC

2020-12-09 09:59:40

Redis原理實(shí)戰(zhàn)

2017-08-24 15:09:13

GAN神經(jīng)網(wǎng)絡(luò)無監(jiān)督學(xué)習(xí)

2023-01-06 12:50:46

ChatGPT

2019-11-11 14:51:19

Java數(shù)據(jù)結(jié)構(gòu)Properties

2022-10-31 09:00:24

Promise數(shù)組參數(shù)

2018-11-09 16:24:25

物聯(lián)網(wǎng)云計(jì)算云系統(tǒng)

2022-11-09 08:06:15

GreatSQLMGR模式

2022-01-11 07:52:22

CSS 技巧代碼重構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)