首页 > 代码库 > android 下Protobuff框架性能测试结果

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 .