FlatBuffers

8516 ワード

データのシーケンス化と逆シーケンス化
データのシーケンス化はプログラムコードの中で不可欠な構成部分であり、データのシーケンス化の性能を議論するとき、どのような候補案があるのか、それぞれのメリットとデメリットは何なのかを知る必要があります.
データシーケンス化の動作は、ネットワーク転送、異なるプロセス間のデータ転送、異なるクラス間のパラメータ転送、ディスクにデータを格納するなど、データ転送中の任意の段階で発生する可能性があります.通常、シーケンス化が必要なクラスをSerializableインタフェースに実装しますが、この従来のアプローチは効率的ではなく、実装プロセスでより多くのメモリが消費されます.
しかし、GSONライブラリを使用してこのシーケンス化の問題を処理すると、実行速度が速いだけでなく、メモリの使用効率も向上します.AndroidのXMLレイアウトファイルは、コンパイルの段階でより複雑なフォーマットに変換され、より効率的な実行性能とより高いメモリ使用効率を備えます.
JSONは可読性が強いが,シーケンス化と逆シーケンス化の性能は最悪である.解析の際、JSON解析器はまず、メモリに対応するデータ構造を初期化する必要があり、このイベントは常に100 ms~200 msを消費する.解析中に大量の一時変数を生成し、Java仮想マシンのGCとメモリジッタを発生させ、20 KBのデータを解析すると、約100 KBの一時メモリが消費される.
3つのデータ・シーケンス化候補
  • Protocal Buffers:強力で柔軟ですが、メモリの消費量は比較的大きく、モバイル端末での最適な選択ではありません.
  • Nano-Proto-Buffers:Protocalに基づいて、モバイル端末のために特別な最適化を行い、コードの実行効率が高く、メモリの使用効率がより良い.
  • FlatBuffers:このオープンソースライブラリは、Googleが開発したもので、より優れたパフォーマンスを提供することに専念しています.上記のスキームの性能に関するデータ対は、例えば、下図に示すように、
  • である.
    FlatBuffersは他の技術にほぼ空間と時間の複雑さから勝っていることがわかる.
    FlatBuffer
    FlatBufferはバイナリファイルに基づいており、jsonは文字列に基づいている.
    FlatBuffers               ,           (C++, C#, Go, Java, JavaScript, PHP, Python)。
         Google                     。     GitHub 。     https://github.com/google/flatbuffers。
    

    メリット
  • シーケンス化データを直接読み取り、解析(Parsing)やUnpacking(Unpacking):FlatBufferはデータ階層構造をフラット化されたバイナリキャッシュ(1次元配列)に保存するとともに、解析を必要とせずに直接中の構造化データを取得することができ、データ構造の変化の前後互換性を保証することができる.
  • の効率的なメモリ使用と速度:FlatBufferの使用中、メモリ内の元のデータのサイズに近い追加のメモリは必要ありません.
  • 柔軟性:データは前後互換性があり、データ構造を柔軟に制御できます.
  • の少ないコード侵入性:少量の自動生成コードで実現できる.
  • はデータクラス性が強く、使いやすく、プラットフォームにまたがり、ほとんど言語に関係ありません.

  • 欠点
  • FlatBuffersはコードを生成する必要があり、コードに侵入性がある.
  • データのシーケンス化は可読性がなく、Debugが不便である.
  • FlatBuffersオブジェクトを構築するのは面倒で、直感的ではありません.特に、オブジェクトが複雑な場合、大きなセグメントのコードを書く必要があります.データのすべての内容はSchemaで厳密に定義する必要があり、柔軟性はJSON
  • に及ばない.
    FlatBufferの使用
  • 参照json
  • {
      "result": [
        {
          "id": "110000",
          "title": "   ",
          "city": [
            {
              "id": "110100",
              "title": "   ",
              "children": [
                {
                  "id": "110101",
                  "title": "   ",
                  "value": 1
                }
              ]
            }
          ]
        }]}
    
  • Schemaデータ構造を定義addressを記述する.fbsファイル
  • table ResultList {
        result : [Result];
    }
    
    table Result {
        id : string;
        title : string;
        city : [City];
    }
    
    table City {
        id : string;
        title : string;
         children : [Children];
    }
    
    table Children {
        id : string;
        title : string;
        value:int;
        isCore:bool;
        code:long;
    }
    
    root_type ResultList;
    
  • flatcによってこのSchemaをコンパイルし、javaファイルを生成する(flatcツールは資料圧縮パッケージ内で解凍し、現在のディレクトリはcmdを開くだけでよい)
  • flatc -j -b address.fbs
    
  • 生成されるファイルおよびFlatBufferBuilder.java、Table.JAvaはアンドロイドプロジェクトに入れます(この2つのファイルは資料圧縮パッケージ内です)
  •        ,          。
               。
    
    
    package cn.gxh.property.Lsn13;// automatically generated, do not modify
    
    //      ,        
    package ;
    
    import java.nio.*;
    import java.lang.*;
    import java.util.*;
    //      
    import com.google.flatbuffers.*;
    
    //            
    public class ResultList extends Table {
      public static ResultList getRootAsResultList(ByteBuffer _bb) { return getRootAsResultList(_bb, new ResultList()); }
      public static ResultList getRootAsResultList(ByteBuffer _bb, ResultList obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
      public ResultList __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
    
      public Result result(int j) { return result(new Result(), j); }
      public Result result(Result obj, int j) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
      public int resultLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; }
    
      public static int createResultList(FlatBufferBuilder builder,
          int result) {
        builder.startObject(1);
        ResultList.addResult(builder, result);
        return ResultList.endResultList(builder);
      }
    
      public static void startResultList(FlatBufferBuilder builder) { builder.startObject(1); }
      public static void addResult(FlatBufferBuilder builder, int resultOffset) { builder.addOffset(0, resultOffset, 0); }
      public static int createResultVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); }
      public static void startResultVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); }
      public static int endResultList(FlatBufferBuilder builder) {
        int o = builder.endObject();
        return o;
      }
      public static void finishResultListBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); }
    };
    
    
  • 書き込みコード
  • private void serialize() {
            FlatBufferBuilder builder = new FlatBufferBuilder();
            //  
            int children1 = Children.createChildren(builder, builder.createString("1001"),
                    builder.createString("   "), 1, true, 10000009);
            int children2 = Children.createChildren(builder, builder.createString("1002"),
                    builder.createString("   "), 2, true, 10000008);
    
            int[] childrens = new int[2];
            childrens[0] = children1;
            childrens[1] = children2;
            int childrenVector = City.createChildrenVector(builder, childrens);
    
            // 
            int city = City.createCity(builder, builder.createString("101"),
                    builder.createString("   "), childrenVector);
    
            int[] cities = new int[2];
            cities[0] = city;
            int cityVector = Result.createCityVector(builder, cities);
            int result = Result.createResult(builder, builder.createString("100"),
                    builder.createString("   1"), cityVector);
    
            int[] results=new int[2];
            results[0]=result;
            int resultVector = ResultList.createResultVector(builder, results);
    
    
            ResultList.startResultList(builder);
            ResultList.addResult(builder, resultVector);
            int rootResult = ResultList.endResultList(builder);
            ResultList.finishResultListBuffer(builder, rootResult);
    
            //-------       ------
            File sdcard = Environment.getExternalStorageDirectory();
            File file = new File(sdcard, "address.txt");
            if (file.exists()) {
                file.delete();
            }
    
            ByteBuffer byteBuffer = builder.dataBuffer();
            FileOutputStream fos = null;
            FileChannel channel = null;
            try {
                fos = new FileOutputStream(file);
                channel = fos.getChannel();
                while (byteBuffer.hasRemaining()) {
                    channel.write(byteBuffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fos != null) {
                        fos.close();
                    }
    
                    if (channel != null) {
                        channel.close();
                    }
                } catch (Exception e) {
                }
    
            }
    
    
            //------    --------
            FileInputStream fis = null;
            FileChannel readChannel = null;
            try {
                fis = new FileInputStream(file);
                readChannel = fis.getChannel();
                ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
                int readBytes = 0;
                while ((readBytes = readChannel.read(byteBuffer1)) != -1) {
    
                }
    
                //          
                byteBuffer1.flip();
                ResultList resultList = ResultList.getRootAsResultList(byteBuffer1);
                Global.showToast(resultList.result(0).id()+";"+resultList.result(0).title());
                Log.d("gxh",resultList.result(0).id()+";"+resultList.result(0).title());
    
            } catch (Exception e) {
    
            }finally {
                try {
                    if (fis != null) {
                        fis.close();
                    }
    
                    if (readChannel != null) {
                        readChannel.close();
                    }
                } catch (Exception e) {
                }
            }
    
        }
    

    リソース圧縮パッケージをアップロードしました.ポイントがなければ、メールボックスに連絡してください.