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;}@Overrideprotected 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;}@Overrideprotected 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;}@Overrideprotected 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;}@Overrideprotected 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 .
由于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("開始測試"); } } } |
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("開始測試"); } } } |
posted on 2014-07-28 09:34 順其自然EVO 閱讀(1878) 評論(0) 編輯 收藏 所屬分類: android