網(wǎng)上有很多關(guān)于pos機(jī)解碼2015,pytorch代碼實(shí)戰(zhàn)transformer模型——基于英譯漢機(jī)器翻譯數(shù)據(jù)集的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)解碼2015的問(wèn)題,今天pos機(jī)之家(m.afbey.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!
本文目錄一覽:
pos機(jī)解碼2015
一 前言FlatBuffers 是一個(gè)開源的、跨平臺(tái)的、高效的、提供了多種語(yǔ)言接口的序列化工具庫(kù)。實(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)行研究并分享于此。本文簡(jiǎn)單介紹 FlatBuffers Scheme,通過(guò)剖析 FlatBuffers 序列化與反序列化原理,重點(diǎn)回答以下問(wèn)題:
問(wèn)題1:FlatBuffers 如何做到反序列化速度極快的(或者說(shuō)無(wú)需解碼)。問(wèn)題2:FlatBuffers 如何做到默認(rèn)值不占存儲(chǔ)空間的(Table 結(jié)構(gòu)內(nèi)的變量)。問(wèn)題3:FlatBuffers 如何做到字節(jié)對(duì)齊的。問(wèn)題4:FlatBuffers 如何做到向前向后兼容的(Struct 結(jié)構(gòu)除外)。問(wèn)題5:FlatBuffers 在 add 字段時(shí)有沒(méi)有順序要求(Table 結(jié)構(gòu))。問(wèn)題6:FlatBuffers 如何根據(jù) Scheme 自動(dòng)生成編解碼器。問(wèn)題7:FlatBuffers 如何根據(jù) Scheme 自動(dòng)生成 json。二 FlatBuffers SchemeFlatBuffers 通過(guò) Scheme 文件定義數(shù)據(jù)結(jié)構(gòu),Schema 定義與其他框架使用的IDL(Interface description language)語(yǔ)言類似簡(jiǎn)單易懂,F(xiàn)latBuffers 的 Scheme 是一種類 C 的語(yǔ)言(盡管 FlatBuffers 有自己的接口定義語(yǔ)言 Scheme 來(lái)定義要與之序列化的數(shù)據(jù),但它也支持 Protocol Buffers 中的 .proto 格式)。下面以官方 Tutorial 中的 monster.fbs 為例進(jìn)行說(shuō)明:
// 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 來(lái)說(shuō)比較節(jié)省內(nèi)存。union 跟 enum 比較類似,但是 union 包含的是 table,enum 包含的是 scalar 或者 struct。union 也只能作為 table 的一部分,不能作 root type。
struct Vect3{ x : float; y : float; z : float;};
struct 所有字段都是必填的,因此沒(méi)有默認(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)值,如果沒(méi)有明確寫出則默認(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ì)生成該字段的訪問(wèn)器。如果需要嵌套的 Vector,可以將 vector 包裝在 table 中。string 對(duì)于其他編碼可以使用 [byte] 或者 [ubyte] 支持。三 FlatBuffers 的序列化簡(jiǎn)單來(lái)說(shuō) 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é)順序來(lái)確保 buffer 是跨平臺(tái)的。此外,對(duì)于 table 對(duì)象,F(xiàn)latBuffers 提供前向/后向兼容性和 optional 字段,以支持大多數(shù)格式的演變。除了解析效率以外,二進(jìn)制格式還帶來(lái)了另一個(gè)優(yōu)勢(shì),數(shù)據(jù)的二進(jìn)制表示通常更具有效率。我們可以使用 4 字節(jié)的 UInt 而不是 10 個(gè)字符來(lái)存儲(chǔ) 10 位數(shù)字的整數(shù)。
FlatBuffers 對(duì)序列化基本使用原則:
小端模式。FlatBuffers 對(duì)各種基本數(shù)據(jù)的存儲(chǔ)都是按照小端模式來(lái)進(jìn)行的,因?yàn)檫@種模式目前和大部分處理器的存儲(chǔ)模式是一致的,可以加快數(shù)據(jù)讀寫的數(shù)據(jù)。寫入數(shù)據(jù)方向和讀取數(shù)據(jù)方向不同。FlatBuffers 向 ByteBuffer 中寫入數(shù)據(jù)的順序是從 ByteBuffer 的尾部向頭部填充,由于這種增長(zhǎng)方向和 ByteBuffer 默認(rèn)的增長(zhǎng)方向不同,因此 FlatBuffers 在向 ByteBuffer 中寫入數(shù)據(jù)的時(shí)候就不能依賴 ByteBuffer 的 position 來(lái)標(biāo)記有效數(shù)據(jù)位置,而是自己維護(hù)了一個(gè) space 變量來(lái)指明有效數(shù)據(jù)的位置,在分析 FlatBuffersBuilder 的時(shí)候要特別注意這個(gè)變量的增長(zhǎng)特點(diǎn)。但是,和數(shù)據(jù)的寫入方向不同的是,F(xiàn)latBuffers 從 ByteBuffer 中解析數(shù)據(jù)的時(shí)候又是按照 ByteBuffer 正常的順序來(lái)進(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ù)訪問(wèn)。
示例: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)闆](méi)有使用 vtable 結(jié)構(gòu),因此內(nèi)部的標(biāo)量沒(méi)有默認(rèn)值,必須存儲(chǔ)(struct 類型和 table 類型的序列化原理在下文會(huì)詳細(xì)說(shuō)明)。
// 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ì)齊。通過(guò) 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ù)訪問(wèn)。FlatBuffers 規(guī)定 Struct 類型用于存儲(chǔ)那些約定成俗、永不改變的數(shù)據(jù),這種類型的數(shù)據(jù)結(jié)構(gòu)一旦確定便永遠(yuǎn)不會(huì)改變,沒(méi)有任何字段是可選的(也沒(méi)有默認(rèn)值),字段可能不會(huì)被添加或被棄用,所以 structs 不提供前向/后向兼容性。在這個(gè)規(guī)定之下,為了提高數(shù)據(jù)訪問(wèn)速度,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 中也沒(méi)有單獨(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 來(lái)實(shí)現(xiàn)。string 本質(zhì)上也可以看做是 byte 的 vector ,因此創(chuàng)建過(guò)程和 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 中沒(méi)有特定類型表示 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 類型來(lái)解析 Union 對(duì)應(yīng)的數(shù)據(jù)。
6 Enum 類型
FlatBuffers 中的 enum 類型在數(shù)據(jù)存儲(chǔ)的時(shí)候是和 byte 類型存儲(chǔ)的方式一樣的。因?yàn)楹?Union 類型相似,enum 類型在 FlatBuffers 中也沒(méi)有單獨(dú)的類與它對(duì)應(yīng),在 schema 中聲明為 enum 的類會(huì)被編譯生成單獨(dú)的類。
enum 類型不能是一個(gè) schema 文件的根。7 Table 類型
table 是 FlatBuffers 的基石,為了解決數(shù)據(jù)結(jié)構(gòu)變更的問(wèn)題,table 通過(guò) vtable 間接訪問(wèn)字段。每個(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 很小并且共享)訪問(wèn)成本也很?。ㄩg接訪問(wèn)),但是提供了很大的靈活性。table 在特殊情況下可能比等價(jià)的 struct 花費(fèi)更少的內(nèi)存,因?yàn)樽侄卧诘扔谀J(rèn)值時(shí)不需要存儲(chǔ)在 buffer 中。這樣的結(jié)構(gòu)決定了一些復(fù)雜類型的成員都是使用相對(duì)尋址進(jìn)行數(shù)據(jù)訪問(wèn)的,即先從Table 中取到成員常量的偏移,然后根據(jù)這個(gè)偏移再去常量真正存儲(chǔ)的地址去取真實(shí)數(shù)據(jù)。
單就結(jié)構(gòu)來(lái)講:首先可以將 Table 分為兩個(gè)部分,第一部分是存儲(chǔ) Table 中各個(gè)成員變量的概要,這里命名為 vtable,第二部分是 Table 的數(shù)據(jù)部分,存儲(chǔ) Table 中各個(gè)成員的值,這里命名為 table_data。注意 Table 中的成員如果是簡(jiǎn)單類型或者 Struct 類型,那么這個(gè)成員的具體數(shù)值就直接存儲(chǔ)在 table_data中;如果成員是復(fù)雜類型,那么 table_data 中存儲(chǔ)的只是這個(gè)成員數(shù)據(jù)相對(duì)于寫入地址的偏移,也就是說(shuō)要獲得這個(gè)成員的真正數(shù)據(jù)還要取出 table_data 中的數(shù)據(jù)進(jìn)行一次相對(duì)尋址。
vtable 是一個(gè) short 類型的數(shù)組,其長(zhǎng)度為(字段個(gè)數(shù)+2)*2字節(jié),第一個(gè)字段是 vtable 的大小,包括這個(gè)大小本身;第二個(gè)字段是 vtable 對(duì)應(yīng)的對(duì)象的大小,包括到 vtable 的 offset;接下來(lái)是每個(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)的是通過(guò) vtable - table_data 機(jī)制存儲(chǔ)的,這個(gè)操作沒(méi)有強(qiáng)制要求字段的先后順序,對(duì)順序沒(méi)有要求,因?yàn)関table在記錄每個(gè)字段相對(duì)于對(duì)象開始位置的 offset 時(shí)是按照 schema 中定義的順序進(jìn)行存儲(chǔ)的,所以在add字段的時(shí)候即使沒(méi)有順序也可以根據(jù) offset 獲取正確的值。需要注意的是,每次add字段時(shí) FlatBuffers 都會(huì)做字節(jié)對(duì)齊處理。
std::string e_poiId = "1234567890";double e_coord_x = 0.1; double 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é)。
std::string e_poiId = "1234567890";double e_coord_x = 0.1; double 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í)有沒(méi)有順序要求。序列化后的數(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)值,如果沒(méi)有明確寫出則默認(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 反序列化的過(guò)程就很簡(jiǎn)單了。由于序列化的時(shí)候保存好了各個(gè)字段的 offset,反序列化的過(guò)程其實(shí)就是把數(shù)據(jù)從指定的 offset 中讀取出來(lái)。反序列化的過(guò)程是把二進(jìn)制流從 root table 往后讀。從 vtable 中讀取對(duì)應(yīng)的 offset,然后在對(duì)應(yīng)的 object 中找到對(duì)應(yīng)的字段,如果是引用類型,string / vector / table,讀取出 offset,再次尋找 offset 對(duì)應(yīng)的值,讀取出來(lái)。如果是非引用類型,根據(jù) vtable 中的 offset ,找到對(duì)應(yīng)的位置直接讀取即可。對(duì)于標(biāo)量,分 2 種情況,默認(rèn)值和非默認(rèn)值。默認(rèn)值的字段,在讀取的時(shí)候,會(huì)直接從 flatc 編譯后的文件中記錄的默認(rèn)值中讀取出來(lái)。非默認(rèn)值字段,二進(jìn)制流中就會(huì)記錄該字段的 offset,值也會(huì)存儲(chǔ)在二進(jìn)制流中,反序列化時(shí)直接根據(jù)offset讀取字段值即可。
整個(gè)反序列化的過(guò)程零拷貝,不消耗占用任何內(nèi)存資源。并且 FlatBuffers 可以讀取任意字段,而不是像 Json 和 protocol buffer 需要讀取整個(gè)對(duì)象以后才能獲取某個(gè)字段。FlatBuffers 的主要優(yōu)勢(shì)就在反序列化這里了。所以 FlatBuffers 可以做到解碼速度極快,或者說(shuō)無(wú)需解碼直接讀取。
五 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)是避免反序列化。通過(guò)定義二進(jìn)制數(shù)據(jù)協(xié)議來(lái)實(shí)現(xiàn)的,一種將定義好的將數(shù)據(jù)轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)的方法。由該協(xié)議創(chuàng)建的二進(jìn)制結(jié)構(gòu)無(wú)需進(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 通過(guò) Scheme 文件定義數(shù)據(jù)結(jié)構(gòu),Schema 定義與其他框架使用的IDL(Interface description language)語(yǔ)言類似簡(jiǎn)單易懂,F(xiàn)latBuffers 的 Scheme 是一種類C的語(yǔ)言(盡管 FlatBuffers 有自己的接口定義語(yǔ)言Scheme來(lái)定義要與之序列化的數(shù)據(jù),但它也支持 Protocol Buffers 中的 .proto 格式)。下面以官方 Tutorial 中的 monster.fbs 為例進(jìn)行說(shuō)明:
1 優(yōu)點(diǎn)
解碼速度極快,將序列化數(shù)據(jù)存儲(chǔ)在緩存中,這些數(shù)據(jù)既可以寫出至文件中,又可以通過(guò)網(wǎng)絡(luò)原樣傳輸,也可直接讀取而沒(méi)有任何解析開銷,訪問(wèn)數(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,而不需要任何依賴庫(kù),在最新的 gcc、clang、vs2010 等編輯器上也工作良好。使用簡(jiǎn)單方便 ,僅僅需要自動(dòng)生成的少量代碼和一個(gè)單一的頭文件依賴,很容易集成到現(xiàn)有系統(tǒng)中,生成的 C++ 代碼提供了簡(jiǎn)單的訪問(wèn)和構(gòu)造接口,可以兼容 Json 等其他格式的解析。2 缺點(diǎn)
數(shù)據(jù)無(wú)可讀性,必須進(jìn)行數(shù)據(jù)可視化才能理解數(shù)據(jù)。向后兼容性局限,在 schema 中添加或刪除字段必須小心。七 總結(jié)相比其它的序列化工具,F(xiàn)latBuffers 最大的優(yōu)勢(shì)是反序列化速度極快,或者說(shuō)無(wú)需解碼。如果使用場(chǎng)景是需要經(jīng)常解碼序列化的數(shù)據(jù),則有可能從 FlatBuffers 的特性獲得一定的好處。
作者 | 大向
原文鏈接:http://click.aliyun.com/m/1000284601/
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
以上就是關(guān)于pos機(jī)解碼2015,pytorch代碼實(shí)戰(zhàn)transformer模型——基于英譯漢機(jī)器翻譯數(shù)據(jù)集的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)解碼2015的知識(shí),希望能夠幫助到大家!
