FlatBuffers去年發布,最近看了1下,與同是出自Google之手的Protocol Buffers非常類似。在官網上介紹,FlatBuffers(簡稱FB)主要針對game development和對性能有要求的利用。相對Protocol Buffers(簡稱PB),FB不需要解析,只通過序列化后的2進制buffer便可完成數據訪問。
FB的主要特點有:
1)數據訪問不需要解析
將數據序列化成2進制buffer,以后的數據訪問直接讀取這個buffer,所以讀取的效力很高。
2)內存高效、速度快
- 數據訪問只在序列化后的2進制buffer,不需額外的內存分配。
- 數據訪問速度接近原生的struct,只多了1次解援用(根據起始地址和偏移量,然后取值)
3)彈性
都是可選字段,支持向前、向后兼容
4)生成的代碼量小
只需依賴1個頭文件
5)強類型
編譯時檢測毛病
6)易于使用
可以解析schema和json文本
7)跨平臺
C++/Java/Go不需額外依賴
FB的實現原理:
通過FB序列化后的數據就是1個2進制buffer,內部包括各種objects(structs,tables,vectors),通過offset組織。所以數據可以in-place訪問(起始地址+偏移量),就像數組或struct訪問。
FB中table代表1個數據結構,這個table會對應1個vtable,用于唆使各個字段在buffer中的偏移量。接下來,在訪問某個字段時,直接根據偏移量就能夠找到該字段。 由于FB直接訪問raw buffer,所以在數據破壞時,會得到臟數據。FB通過Verifier確保不可信buffer數據是正確的。
下面測試了PB和FB,做性能對照,測試場景很簡單,構造N個對象,序列化,寫入文件,然后再反序列化。測試的對象結構以下:
記錄個數 | FlatBuffers | Protocol Buffers |
10000 | 0.197 / 4.4M / 0.02 | 0.166 / 3.0M / 0.08 |
20000 | 0.383 / 8.8M / 0.03 | 0.248 / 6.4M / 0.168 |
30000 | 0.534 / 13M / 0.05 | 0.378 / 10M / 0.26 |
100000 | 1.937 / 44M / 0.144 | 1.314 / 38M / 0.8 |
200000 | 3.9 / 88M / 0.276 | 2.66 / 67M / 1.542 |
1000000 | 17.59 / 439M / 1.396 | 13.355 / 397M / 8.012 |
X / Y / Z3個數據,分別對應,序列化總時間 / 文件大小 / 反序列時間,其中包括讀寫文件的時間。可以看到,PB在序列化的時間和大小都要優于FB,序列化要快30%左右,序列化數據大小要小20%左右。而FB由于不需要解析,反序列化異常快。
雖然FB的反序列化超級快,但是數據大小還是蠻大的(可能的緣由是不需要解析,直接訪問binary buffer,所以不能對數據進行緊縮),帶來的傳輸或存儲開消,可能會抵過1部份反序列化的時間。感覺上,FB的使用處景上還是很受限,在移動端多是1個利用場景。
測試代碼為了簡單,對每一個對象都會調用write或read,統計的時間也包括這些時間。由于要對PB和FB對照,此部份開消基本1致。具體代碼見github