android 下Protobuff框架性能测试结果

android 下Protobuff常用的框架有三个: protobuff自身,  square出的wire , protostuff

由于protobuff会为每个属性生成大量不常用的方法,当程序比较复杂时容易超过android的60K个方法的上限, 所以本次测试未包括protobuff

测试逻辑是循环100次序列化100个元素的数组,并反序列化,求平均值,代码如下:

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的测试代码:

    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("开始测试");
            }
        }
    }

 

测试结果为(单位豪秒):

手机环境:魅族MX2

1) wire 1.5.1 ,网址 https://github.com/square/wire

     avg: 1860~1907 , 最小值约为1500左右,极少出现, 全过程随机分布

   avg deserializeTime: 9~10, 最小值约为5,极少出现,全过程随机分布

 

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 .

android 下Protobuff框架性能测试结果,布布扣,bubuko.com

android 下Protobuff框架性能测试结果

上一篇:Fast-tracking approach for building routing topologies in fast-moving networks


下一篇:用开源AOP简化MVVM框架