android 下Protobuff框架性能測試結果

android 下Protobuff經常使用的框架有三個: protobuff自身,  square出的wire , protostuffandroid

因爲protobuff會爲每一個屬性生成大量不經常使用的方法,當程序比較複雜時容易超過android的60K個方法的上限, 因此本次測試未包括protobuffgit

測試邏輯是循環100次序列化100個元素的數組,並反序列化,求平均值,代碼以下:github

wire的測試代碼:數組

    public void onClickButton(View view){
        if (TestTask.isCancel){
            TestTask.isCancel = false;
            TestTask.sumDeserializeTime = 0;
            TestTask.sumTime = 0;
            TestTask.runCount = 0;
            TextView text1 = (TextView) findViewById(R.id.textView2);
            text1.setText("");
            new TestTask( (TextView) findViewById(R.id.textView2)
                    , (TextView) findViewById(R.id.button1)).execute();
            ((TextView)view).setText("測試中,點擊中斷");
        }else{
            ((TextView)view).setText("正在中斷...");
            TestTask.isCancel = true;
        }
    }
    
    static class TestTask extends AsyncTask<Void,Void,Long>{
        long serializeTime=0;
        long deserializeTime=0;

        static long sumTime=0;
        static long sumDeserializeTime=0;
        static int runCount=0;
        static boolean isCancel=true;
        
        TextView text1;
        TextView btn;
        public TestTask(TextView text1,TextView btn) {
            this.text1 = text1;
            this.btn = btn;
        }
        
        @Override
        protected Long doInBackground(Void... params) {
            long startTime = System.currentTimeMillis();
            
            for (int i = 0; i < 100; i++) {
                List<ListItem> itemList = new ArrayList<ListItem>();
                ListItem.Builder itemBuilder = new ListItem.Builder();
                ListItem item;
                for (int j = 0; j < 100; j++) {
                    item = itemBuilder.title("test Title"+i+":"+j)
                                      .remark("test Remark"+i+":"+j)
                                      .coverUrl("http://pic.ozreader.com/abc.pic")
                                      .uri("PKB:TESTURI")
                                      .build();
                    itemList.add(item);
                }
                
                ScrollList.Builder listBuilder= new ScrollList.Builder();
                ScrollList list = listBuilder.haveMore(false).tags(itemList).build();
                byte[] dataBuffer = list.toByteArray();
                serializeTime = System.currentTimeMillis()-startTime;
                
                Wire wire = new Wire();
                try {
                    ScrollList resultList = wire.parseFrom(dataBuffer, ScrollList.class);
                    if (resultList == null){
                        Log.e("TEST", "resultList is null");
                        break;
                    }else if (resultList.tags == null){
                        Log.e("TEST", "resultList.tags is null");
                        break;
                    }else if (resultList.tags.size() <= 0){
                        Log.e("TEST", "resultList.tags is empty");
                        break;
                    }else if (resultList.tags.size() != 100){
                        Log.e("TEST", "resultList.tags is wrong");
                        break;
                    }else if (!resultList.tags.get(0).uri.equals("PKB:TESTURI")){
                        Log.e("TEST", "resultList.tags content is wrong");
                        break;
                    }
                    deserializeTime = System.currentTimeMillis()-startTime-serializeTime;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return System.currentTimeMillis() - startTime;
        }
        
        @Override
        protected void onPostExecute(Long result) {
            sumTime += result;
            sumDeserializeTime += deserializeTime;
            runCount ++;
            text1.append("result:"+result+", serializeTime:"+serializeTime+", deserializeTime:"+deserializeTime+", runCount:"+runCount+", avg:"+sumTime/runCount+", avg deserializeTime:"+sumDeserializeTime/runCount+"\n");

            if (isCancel){
                text1.append("測試中斷.");
                btn.setText("開始測試");
            }else if (runCount < 100){
                new TestTask(text1,btn).execute();
            }else{
                isCancel = true;
                text1.append("測試完成.");
                btn.setText("開始測試");
            }
        }
        
    }

 

protobuff的測試代碼:app

    public void onClickButton(View view){
        
        if (TestTask.isCancel){
            TestTask.isCancel = false;
       TestTask.sumDeserializeTime = 0;
       TestTask.sumTime = 0;
       TestTask.runCount = 0;
TextView text1 = (TextView) findViewById(R.id.textView2);
            text1.setText("");
            new TestTask( (TextView) findViewById(R.id.textView2)
                    , (TextView) findViewById(R.id.button1)).execute();
            ((TextView)view).setText("測試中,點擊中斷");
        }else{
            ((TextView)view).setText("正在中斷...");
            TestTask.isCancel = true;
        }
    }
    
    static class TestTask extends AsyncTask<Void,Void,Long>{
        long serializeTime=0;
        long deserializeTime=0;

        static long sumTime=0;
        static long sumDeserializeTime=0;
        static int runCount=0;
        static boolean isCancel=true;
        
        TextView text1;
        TextView btn;
        public TestTask(TextView text1,TextView btn) {
            this.text1 = text1;
            this.btn = btn;
        }
        
        
        @Override
        protected Long doInBackground(Void... params) {
            long startTime = System.currentTimeMillis();
            
            for (int i = 0; i < 100; i++) {
                List<ListItem> itemList = new ArrayList<ListItem>();
                ScrollList list = new ScrollList();
                list.setHaveMore(false);
                list.setTagsList(itemList);
                
                ListItem item;
                for (int j = 0; j < 100; j++) {
                    item = new ListItem();
                    item.setTitle("test Title"+i+":"+j);
                    item.setRemark("test Remark"+i+":"+j);
                    item.setCoverUrl("http://pic.ozreader.com/abc.pic");
                    item.setUri("PKB:TESTURI");
                    itemList.add(item);
                }
                
                LinkedBuffer buffer = LinkedBuffer.allocate(1024);
                byte[] dataBuffer = ProtobufIOUtil.toByteArray(list, ScrollList.getSchema(), buffer);
                serializeTime = System.currentTimeMillis()-startTime;
                
                ScrollList resultList = new ScrollList();  
                ProtobufIOUtil.mergeFrom(dataBuffer, resultList, ScrollList.getSchema());
                if (resultList.getTagsList() == null){
                    Log.e("TEST", "resultList.tags is null");
                    break;
                }else if (resultList.getTagsList().size() <= 0){
                    Log.e("TEST", "resultList.tags is empty");
                    break;
                }else if (resultList.getTagsList().size() != 100){
                    Log.e("TEST", "resultList.tags is wrong");
                    break;
                }else if (!resultList.getTagsList().get(0).getUri().equals("PKB:TESTURI")){
                    Log.e("TEST", "resultList.tags content is wrong");
                    break;
                }
                deserializeTime = System.currentTimeMillis()-startTime-serializeTime;
            }
            return System.currentTimeMillis() - startTime;
        }
        
        @Override
        protected void onPostExecute(Long result) {
            sumTime += result;
            sumDeserializeTime += deserializeTime;
            runCount ++;
            text1.append("result:"+result+", serializeTime:"+serializeTime+", deserializeTime:"+deserializeTime+", runCount:"+runCount+", avg:"+sumTime/runCount+", avg deserializeTime:"+sumDeserializeTime/runCount+"\n");

            if (isCancel){
                text1.append("測試中斷.");
                btn.setText("開始測試");
            }else if (runCount < 100){
                new TestTask(text1,btn).execute();
            }else{
                isCancel = true;
                text1.append("測試完成.");
                btn.setText("開始測試");
            }
        }
    }

 

測試結果爲(單位豪秒):框架

手機環境:魅族MX2ide

1) wire 1.5.1 ,網址 https://github.com/square/wire
性能

     avg: 1860~1907 , 最小值約爲1500左右,極少出現, 全過程隨機分佈測試

   avg deserializeTime: 9~10, 最小值約爲5,極少出現,全過程隨機分佈ui

 

2) protostuff 1.0.8 ,網址 https://code.google.com/p/protostuff/

     avg: 1100~1150,很是穩定 , 最小值約爲450左右,主要集中在前幾回循環,循環10次後就穩定在11XX左右,偶有600~800的狀況,屢次重複測試狀況基本一致,觀察自動GC並沒有內存泄漏的問題, 暫時不肯定速度變化的緣由.

   avg deserializeTime: 6, 最小值約爲3,極少出現,主要集中在剛開始,絕大多數爲5,偶有達到16的狀況.

 

分析: wire的性能明顯比不上protostuff, 速度也不太穩定,起落較大.  考慮到protostuff的開發模式是普通的pojo方式,比較方便,不像protobuff和wire的builder方式,超麻煩. 因此最終推薦不是邏輯超複雜的企業app都使用protostuff .

相關文章
相關標籤/搜索