[Note] 2021-04-21FlatBuffers

環(huán)境:macOS

一 使用FlatBuffers序列化數(shù)據(jù)

參考 https://blog.csdn.net/guotianqing/article/details/100097909

1.1 序列化

場(chǎng)景:跨平臺(tái)/語(yǔ)言(C<=>Java),跨進(jìn)程,持久化,網(wǎng)絡(luò)傳輸(RMI傳輸對(duì)象等)
概念:數(shù)據(jù)結(jié)構(gòu)/對(duì)象 => 二進(jìn)制串 (反序列化:數(shù)據(jù)結(jié)構(gòu)/對(duì)象 <= 二進(jìn)制)
性能維度:通用性(跨平臺(tái)/語(yǔ)言),空間,時(shí)間,兼容/拓展性,安全/訪(fǎng)問(wèn)限制
序列化工具: XML, SOAP, Protobuf, FlatBuffers, SBE(Simple Binary Encoding), Cap'n Proto

1.2 FlatBuffers

1.2.1 優(yōu)點(diǎn):

  • 使用簡(jiǎn)單,定義協(xié)議文件(schema)、編譯成源碼、操作數(shù)據(jù)
  • 效率高,數(shù)據(jù)在緩沖區(qū)內(nèi)都是平整的,可以直接訪(fǎng)問(wèn)
  • 使用便利,協(xié)議文件設(shè)計(jì)好后可以發(fā)布,可以隨時(shí)往Table里面添加或者刪除成員

1.2.2 缺點(diǎn):

  • 效率高的同時(shí)導(dǎo)致cpu資源占用相對(duì)較高
  • 傳輸?shù)臄?shù)據(jù)可能比對(duì)數(shù)據(jù)進(jìn)行壓縮后再傳輸要大
  • 打包后的FlatBuffers中的矢量數(shù)據(jù)不能隨意修改(一般打包后直接發(fā)送,沒(méi)有這個(gè)需求)
  • FlatBuffers傳輸?shù)臄?shù)據(jù)沒(méi)有JSON、XML和HTML那么直觀

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

  • struct
    Struct 標(biāo)量,修改時(shí)需要全量編譯;優(yōu)點(diǎn)是訪(fǎng)問(wèn)速度快,占用內(nèi)存少。
  • Table
    Table 矢量,可以增刪,刪除時(shí)定義為deprecated(向后兼容)
  • root_type
    是一個(gè)頂級(jí)類(lèi)型。
  • union
    聯(lián)合

標(biāo)量都是直接寫(xiě)到緩沖區(qū)去的,所有的矢量需要先寫(xiě)到緩沖區(qū),然后獲得偏移量(32位),然后再把偏移量寫(xiě)到適當(dāng)?shù)慕Y(jié)構(gòu)中,每個(gè)矢量都離不開(kāi)一個(gè)偏移量。

1.2.4 數(shù)據(jù)類(lèi)型

  • 標(biāo)量
    8 bit: byte (int8), ubyte (uint8), bool
    16 bit: short (int16), ushort (uint16)
    32 bit: int (int32), uint (uint32), float (float32)
    64 bit: long (int64), ulong (uint64), double (float64)
    括號(hào)內(nèi)的名字是它前面類(lèi)型的別名,兩者使用方式等價(jià)。
  • 矢量類(lèi)型包括:
    向量,使用[type]形式
    string,僅支持UTF-8或者7位ASCII碼,其他編碼或者通常的二進(jìn)制數(shù)據(jù)可以使用向量[byte]/[ubyte]替代
    引用其他tables/structs/enums/unions

1.2.5 使用步驟

  • 編寫(xiě) schema 文件,描述數(shù)據(jù)結(jié)構(gòu)和接口定義。
  • 用 flatc 編譯,生成相應(yīng)語(yǔ)言的代碼文件。
  • 使用 FlatBuffers 支持的語(yǔ)言(如C ++,Java等)生成的文件進(jìn)行開(kāi)發(fā)。

1.2.6 橫向?qū)Ρ?/h3>

非扁平化(多層鍵值對(duì)結(jié)構(gòu))數(shù)據(jù)和等效的扁平化(多維數(shù)組)數(shù)據(jù)* 數(shù)據(jù)量小、快速迭代、包含大量字符串數(shù)據(jù),使用JSON,方便快捷;

  • 數(shù)據(jù)量小、接口穩(wěn)定、靜態(tài)語(yǔ)言主導(dǎo)、多語(yǔ)言協(xié)作、集成IDL、依賴(lài)gPRC,考慮 protocol buffers。
  • 數(shù)據(jù)量大、接口穩(wěn)定、靜態(tài)語(yǔ)言主導(dǎo)、集成IDL、數(shù)據(jù)無(wú)法扁平化,考慮 flat buffers。
  • 數(shù)據(jù)量大、快速迭代、性能要求高、數(shù)據(jù)可以扁平化,不希望使用重量級(jí)工具或修改工程結(jié)構(gòu),考慮DIMBIN。

二 Android 使用 FlatBuffers

  1. 準(zhǔn)備 flatc 的編譯工具
  2. 導(dǎo)入 flatbuffers java庫(kù)
  3. FlatBufferBuilder 的使用

2.1 準(zhǔn)備 flatc 的編譯工具

下載編譯 FlatBuffers

$ cd flatbuffers-1.12.0
$ cmake .
$ make 
$ make install
$ flatc --version

2.3 導(dǎo)入 flatbuffers java庫(kù)

  • Maven 導(dǎo)入 implementation 'com.google.flatbuffers:flatbuffers-java:1.12.0'
  • 或者源碼導(dǎo)入為模塊 https://github.com/google/flatbuffers/tree/master/java/com/google/flatbuffers
    然后進(jìn)行依賴(lài) implementation project(path: ':flatbuffers')

2.4 FlatBufferBuilder 的簡(jiǎn)單使用

Kotlin main

  • 創(chuàng)建 .fbs


    image.png
  • 測(cè)試代碼

    fun onClickMainBtn(v: View?) {}

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val fb = FlatBufferBuilder(1024)
            val userOffsetId1 = User.createUser(fb, 41L, fb.createString("haha"), fb.createString("man"))
            val userOffsetId2 = User.createUser(fb, 42L, fb.createString("hiahia"), fb.createString("woman"))

            val usersIds = intArrayOf(userOffsetId1, userOffsetId2)
            val itemsId = RootType.createItemsVector(fb, usersIds)
            val rootTypeId = RootType.createRootType(fb, itemsId)
            // RootType.finishRootTypeBuffer(fb, rootTypeId)
            fb.finish(rootTypeId)
            // write to file
            val file = saveFbToTestFile(fb)
            // read from file
            val bb = ByteBuffer.wrap(file.readBytes())
            // make root type object
            val rRootType = RootType.getRootAsRootType(bb)
            for (i in 0 until rRootType.itemsLength()) {
                val rUser = rRootType.items(i)
                println("${rUser.id()}, ${rUser.name()}, ${rUser.gender()}")
            }
        }

        private fun saveFbToTestFile(fb: FlatBufferBuilder): File {
            val file = File("/Users/lunix/Desktop/flatc_test.txt")
            if (file.exists()) {
                file.delete()
            }
            file.createNewFile()
            file.outputStream().write(fb.dataBuffer().array(), fb.dataBuffer().position(), fb.offset())
            return file
        }
    }

最后

基于效率和性能問(wèn)題,項(xiàng)目慢慢使用 FlatBuffers:

  1. 跨平臺(tái)/語(yǔ)言開(kāi)發(fā)
  2. JSON解析的效率和內(nèi)存問(wèn)題
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容