性能優化13_數據傳輸效率優化

Android性能優化彙總

一 FlatBuffer使用原有

在做 Android 開發的時候,JSON 是最常用的數據序列化技術。JSON 的可讀性很強,但是序列化和反序列化性能卻是最差的。解析的時候,JSON 解析器首先,需要在內存中初始化一個對應的數據結構,這個事件經常會消耗 100ms ~ 200ms2;解析過程中,要產生大量的臨時變量,造成 Java 虛擬機的 GC 和內存抖動,解析 20KB 的數據,大概會消耗 100KB 的臨時內存2。FlatBuffers 就解決了這些問題

二 FlatBuffer

FlatBuffers 是一個開源的跨平臺數據序列化庫,可以應用到幾乎任何語言(C++, C#, Go, Java, JavaScript, PHP, Python),最開始是 Google 爲遊戲或者其他對性能要求很高的應用開發的。項目地址在 GitHub 上。官方的文檔在 這裏。

  1. 直接讀取序列化數據,而不需要解析(Parsing)或者解包(Unpacking):FlatBuffer 把數據層級結構保存在一個扁平化的二進制緩存(一維數組)中,同時能夠保持直接獲取裏面的結構化數據,而不需要解析,並且還能保證數據結構變化的前後向兼容
  2. 高效的內存使用和速度:FlatBuffer 使用過程中,不需要額外的內存,幾乎接近原始數據在內存中的大小
  3. 靈活:數據能夠前後向兼容,並且能夠靈活控制你的數據結構。
  4. 很少的代碼侵入性:使用少量的自動生成的代碼即可實現。
  5. 強數據類性,易於使用,跨平臺,幾乎語言無關。

性能對比
在這裏插入圖片描述

三 使用

1 編寫Model對應的fbs文件

Items.fbs

namespace com.bpj.optimization.optimization.lsn13;
table Items {
    ItemId : long;
    timestemp : int;
    basic:[Basic];
}

table Basic{
	id:int;
	name:string;
	email:int;
	code:long;
	isVip:bool;
	count:int;
	carList:[Car];
}

table Car{
	id:long;
	number:long;
	describle:string;
}

root_type Items;

2 當前目錄下,命令行編譯生成java文件

先下載工具文件
flatc.exeflatc

flatc -j -b fbs文件名.fbs
在這裏插入圖片描述
生成對應的java文件:
在這裏插入圖片描述

3 拷貝java文件到項目中使用

同時拷貝的還有庫提供的FlatBufferBuilder.javaTable.java文件,修改報錯

4 使用

  public void serialize(View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //==================序列化========================
                FlatBufferBuilder builder = new FlatBufferBuilder();
                int id1 = builder.createString("蘭博基尼");
                //準備Car對象
                int car1 = Car.createCar(builder, 10001L, 88888L, id1);
                int id2 = builder.createString("奧迪A8");
                //準備Car對象
                int car2 = Car.createCar(builder, 10001L, 88888L, id2);
                int id3 = builder.createString("奧迪A9");
                //準備Car對象
                int car3 = Car.createCar(builder, 10001L, 88888L, id3);

                int[] cars = new int[3];
                cars[0] = car1;
                cars[1] = car2;
                cars[2] = car3;

                //創建Basic對象裏面的Car集合
                int carList = Basic.createCarListVector(builder, cars);

                int name = builder.createString("ray");
                int email = builder.createString("[email protected]");
                int basic = Basic.createBasic(builder, 10, name, email, 100L, true, 100, carList);
                int basicOffset = Items.createBasicVector(builder, new int[]{basic});
                /**
                 * table Items {
                 ItemId : long;
                 timestemp : int;
                 basic:[Basic];
                 }
                 */
                Items.startItems(builder);
                Items.addItemId(builder, 1000L);
                Items.addTimestemp(builder, 2016);
                Items.addBasic(builder, basicOffset);

                int rootItems = Items.endItems(builder);
                Items.finishItemsBuffer(builder, rootItems);

                //============保存數據到文件=================
                if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
                    Log.e(TAG, "sdcard  un MEDIA_MOUNTED");
                }
                File sdcard = Environment.getExternalStorageDirectory();
                //保存的路徑
                File file = new File(sdcard, "Items.txt");
                if (file.exists()) {
                    file.delete();
                }

                ByteBuffer data = builder.dataBuffer();
                FileOutputStream out = null;
                FileChannel channel = null;
                try {
                    out = new FileOutputStream(file);
                    channel = out.getChannel();
                    while (data.hasRemaining()) {
                        channel.write(data);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (out != null) {
                            out.close();
                        }
                        if (channel != null) {
                            channel.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                //===================反序列化=============================
                FileInputStream fis = null;
                FileChannel readChannel = null;
                try {
                    fis = new FileInputStream(file);
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    readChannel = fis.getChannel();
                    int readBytes = 0;
                    while ((readBytes = readChannel.read(byteBuffer)) != -1) {
                        System.out.println("讀取數據個數:" + readBytes);
                    }
                    //把指針回到最初的狀態,準備從byteBuffer當中讀取數據
                    byteBuffer.flip();
                    //解析出二進制爲Items對象。
                    Items items = Items.getRootAsItems(byteBuffer);
                    //讀取數據測試看看是否跟保存的一致
                    Log.i(TAG, "items.id:" + items.ItemId());
                    Log.i(TAG, "items.timestemp:" + items.timestemp());

                    Basic basic2 = items.basic(0);
                    Log.i(TAG, "basic2.name:" + basic2.name());
                    Log.i(TAG, "basic2.email:" + basic2.email());

                    //carList
                    int length = basic2.carListLength();
                    for (int i = 0; i < length; i++) {
                        Car car = basic2.carList(i);
                        Log.i(TAG, "car.number:" + car.number());
                        Log.i(TAG, "car.describle:" + car.describle());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (readChannel != null) {
                            readChannel.close();
                        }
                        if (fis != null) {
                            fis.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

四 Demo

Lsn13Activity

發佈了231 篇原創文章 · 獲贊 75 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章