FlatBuffers使用小結


  最近做一個Android APP,由於離線業務需求,需要在啟動APP時候同步大量數據到APP上,遇到了JSON性能瓶頸。從下方的圖片中可以看出,當使用 json 傳輸數據,在解析json的時候會產生大量的對象,使得內存瘋狂飆升,不論是配置低端的平板還是配置比較高端的手機都會 GC 。而在使用 flatbuffers 的時候不論是平板還是手機,都沒有 GC,並且在時間是數量級的差別。0.5s與0.05s的差距對你而言或許並不大,但是1s和10s的差距就很明顯了噻,應該沒人能忍受一個app的反應時間需要10s之久吧...

  下面是我測試的參數與測試結果,對比提升可以說是相當的明顯了。注(這里的解析時間是指:從發起請求到響應后把數據解析成對象的時間,也就是說除去相差不多的網絡傳輸時間,單純的對數據的解析時間 faltbuffers 提升會更加明顯 )

 

什么是 FlatBuffers ?

  FlatBuffers是一個高效的跨平台序列化庫,適用於C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust 和Swift。它們最早由谷歌創立,用來開發游戲和其他一些需要高性能的程序。

為什么使用 FlatBuffers 會這么快?

  無需解析/拆包即可訪問序列化數據-FlatBuffers的與眾不同之處在於,它在平坦的二進制緩沖區中表示層次結構數據,使得無需解析/拆包就可以直接訪問它,同時還支持數據結構的演進(forward /向后兼容)

如何使用 FlatBuffers ?

1.編譯器下載地址:https://github.com/google/flatbuffers/releases

2.編寫Schema文件 demo.fbs

namespace com.zxz.demo.flatbuffer;

table User {
id : long;
name : string;
gender : string;
departmentId : long;
createTime : string;
enabled : bool;
status : string;
}

table Account {
id : long;
userId : long;
login : string;
password : string;
loginCount : int;
}


table Data {
userList : [User];
accountList : [Account];
}

root_type Data;

3.生成javaBean文件:flatc.exe --java demo.fbs

4.下載 FlatBuffers 源碼:  https://github.com/google/flatbuffers/tree/master/java,或者看看maven倉庫有沒有依賴包引入項目

5.服務端創建數據

public void service() throws Exception {
    HttpServletResponse response = ActionContext.get().getResponse();
    // 1.創建builder
    FlatBufferBuilder builder = new FlatBufferBuilder(1024);
    List<Integer> list1 = new ArrayList<Integer>();
    for (int i = 0; i < 10; i++) {
        long id = 0L;
        int nameOffset = builder.createString("name");
        int genderOffset = builder.createString("gender");
        long departmentId = 0L;
        int createTimeOffset = builder.createString("2021-01-10");
        boolean enabled = true;
        int statusOffset = builder.createString("status");
        // 2.創建User對象返回 offset值
        int createUser = User.createUser(builder, id, nameOffset, genderOffset, departmentId,
                createTimeOffset, enabled, statusOffset);
        list1.add(createUser);
    }
    // 3.把存儲對象offset值的集合轉成數組
    int[] arr1 = list1.stream().mapToInt(Integer::valueOf).toArray();
    // 4.構建User的數據
    int createUsersVector = Data.createUsersVector(builder, arr1);
    // 5.構建Data對象(Data中包含[User])
    Data.startData(builder);
    // 6.添加User的集合
    Data.addUsers(builder, createUsersVector);
    int offset = Data.endData(builder);
    Data.finishDataBuffer(builder, offset);
    // 7.把DataBuffer寫入到IO中
    ServletOutputStream os = response.getOutputStream();
    os.write(builder.dataBuffer().array(), builder.dataBuffer().position(), builder.offset());
    os.close();
}

6.客戶端接收數據

public void onResponse(Call call, Response response) throws IOException {
   byte[] bytes = response.body().bytes(); ByteBuffer bb = ByteBuffer.wrap(bytes); Data data = Data.getRootAsData(bb); }

 

 

==================================END==================================

==============================測試結果截圖===============================

圖一、平板上使用 json 傳輸數據

圖二、手機上使用 json 傳輸數據

圖三、平板上使用 flatbuffers 傳輸數據

 圖四、手機上使用 flatbuffers 傳輸數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM