[笔记]Android性能优化 上
[笔记]Android性能优化 中
[笔记]Android性能优化 下
7.Android性能优化典范-第4季
5.数据呈现的顺序以及结构会对序列化之后的空间产生不小的影响
- gzip
- gzip概念:HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术
- 一般对纯文本内容可压缩到原大小的40%
- 减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间
- okHttp对gzip的支持
- okHttp支持gzip自动解压缩,不需要设置Accept-Encoding为gzip
- 开发者手动设置Accept-Encoding,okHttp不负责解压缩
- 开发者没有设置Accept-Encoding时,则自动添加Accept-Encoding: gzip,自动添加的request,response支持自动解压
- 自动解压时移除Content-Length,所以上层Java代码想要contentLength时为-1
- 自动解压时移除 Content-Encoding
- 自动解压时,如果是分块传输编码,Transfer-Encoding: chunked不受影响
- 我们在向服务器提交大量数据的时候,希望对post的数据进行gzip压缩,需要使用自定义拦截器
import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okio.BufferedSink; import okio.GzipSink; import okio.Okio; public class GzipRequestInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { return chain.proceed(originalRequest); } Request compressedRequest = originalRequest.newBuilder() .header("Content-Encoding", "gzip") .method(originalRequest.method(), gzip(originalRequest.body())) .build(); return chain.proceed(compressedRequest); } private RequestBody gzip(final RequestBody body) { return new RequestBody() { @Override public MediaType contentType() { return body.contentType(); } @Override public long contentLength() { return -1; // 无法提前知道压缩后的数据大小 } @Override public void writeTo(BufferedSink sink) throws IOException { BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); body.writeTo(gzipSink); gzipSink.close(); } }; } } 然后构建OkhttpClient的时候,添加拦截器: OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩 ... .build();
- okHttp支持gzip自动解压缩,不需要设置Accept-Encoding为gzip
- gzip概念:HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术
- 改变数据结构,就是将原始集合按照集合中对象的属性进行拆分,变成多个属性集合的形式.
- 改变数据结构后JSON字符串长度有明显降低
- 使用GZIP对JSON字符串进行压缩,在原始集合中元素数据重复率逐渐变大的情况下,GZIP压缩后的原始JSON字符串长度/GZIP压缩后的改变数据结构的JSON字符串会明显大于1.
- 代码及测试结果如下,结果仅供参考(ZipUtils是网上荡的,且没有使用网上用过的Base64Decoder,Base64Encoder)
public final class ZipUtils { /** * Gzip 压缩数据 * * @param unGzipStr * @return */ public static String compressForGzip(String unGzipStr) { // if (TextUtils.isEmpty(unGzipStr)) { // return null; // } try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(baos); gzip.write(unGzipStr.getBytes()); gzip.close(); byte[] encode = baos.toByteArray(); baos.flush(); baos.close(); // return Base64Encoder.encode(encode); return new String(encode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * Gzip解压数据 * * @param gzipStr * @return */ public static String decompressForGzip(String gzipStr) { // if (TextUtils.isEmpty(gzipStr)) { // return null; // } // byte[] t = Base64Decoder.decodeToBytes(gzipStr); byte[] t = gzipStr.getBytes(); try { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(t); GZIPInputStream gzip = new GZIPInputStream(in); byte[] buffer = new byte[1024]; int n = 0; while ((n = gzip.read(buffer, 0, buffer.length)) > 0) { out.write(buffer, 0, n); } gzip.close(); in.close(); out.close(); return out.toString(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * Zip 压缩数据 * * @param unZipStr * @return */ public static String compressForZip(String unZipStr) { // if (TextUtils.isEmpty(unZipStr)) { // return null; // } try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(baos); zip.putNextEntry(new ZipEntry("0")); zip.write(unZipStr.getBytes()); zip.closeEntry(); zip.close(); byte[] encode = baos.toByteArray(); baos.flush(); baos.close(); // return Base64Encoder.encode(encode); return new String(encode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * Zip解压数据 * * @param zipStr * @return */ public static String decompressForZip(String zipStr) { // if (TextUtils.isEmpty(zipStr)) { // return null; // } // byte[] t = Base64Decoder.decodeToBytes(zipStr); byte[] t = zipStr.getBytes(); try { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(t); ZipInputStream zip = new ZipInputStream(in); zip.getNextEntry(); byte[] buffer = new byte[1024]; int n = 0; while ((n = zip.read(buffer, 0, buffer.length)) > 0) { out.write(buffer, 0, n); } zip.close(); in.close(); out.close(); return out.toString("UTF-8"); } catch (IOException e) { e.printStackTrace(); } return null; } } public class GzipZipTest { public static void main(String[] args) { GzipZipTest t = new GzipZipTest(); t.t(); } private void t(){ /*List<Person> l = new ArrayList<Person>(); for(int i=0;i<1;i++){ for(int j=0;j<6000;j++){ Person p = new Person(); p.age = j; p.gender = "gender"+j; p.name = "name"+j; l.add(p); } } Gson gson = new Gson(); List<String> names = new ArrayList<String>(); List<String> genders = new ArrayList<String>(); List<Integer> ages = new ArrayList<Integer>(); for(Person p:l){ names.add(p.name); genders.add(p.gender); ages.add(p.age); } PersonItemList itemList = new PersonItemList(); itemList.items = l; String jsonDataOri = gson.toJson(itemList); System.out.println("原始数据结构 压缩前json数据长度 ---->" + jsonDataOri.length()); PersonAttrList attrList = new PersonAttrList(); attrList.names = names; attrList.genders = genders; attrList.ages = ages; String jsonDataVariety = gson.toJson(attrList); System.out.println("变种数据结构 压缩前json数据长度 ---->" + jsonDataVariety.length()); System.out.println("==================================================="); for(int i=0;i<100;i++){ //1:原始数据结构 //Gzip压缩 long start = System.currentTimeMillis(); String gzipStr = ZipUtils.compressForGzip(jsonDataOri); long end = System.currentTimeMillis(); System.out.println("原始数据结构 Gzip压缩耗时 cost time---->" + (end - start)); System.out.println("原始数据结构 Gzip压缩后json数据长度 ---->" + gzipStr.length()); //Zip压缩 // start = System.currentTimeMillis(); // String zipStr = ZipUtils.compressForZip(jsonDataOri); // end = System.currentTimeMillis(); // System.out.println("原始数据结构 Zip压缩耗时 cost time---->" + (end - start)); // System.out.println("原始数据结构 Zip压缩后json数据长度 ---->" + zipStr.length()); //2:变种数据结构 //Gzip压缩 start = System.currentTimeMillis(); String gzipStrVariety = ZipUtils.compressForGzip(jsonDataVariety); end = System.currentTimeMillis(); System.out.println("变种数据结构 Gzip压缩耗时 cost time---->" + (end - start)); System.out.println("变种数据结构 Gzip压缩后json数据长度 ---->" + gzipStrVariety.length()); //Zip压缩 // start = System.currentTimeMillis(); // String zipStrVariety = ZipUtils.compressForZip(jsonDataVariety); // end = System.currentTimeMillis(); // System.out.println("变种数据结构 Zip压缩耗时 cost time---->" + (end - start)); // System.out.println("变种数据结构 Zip压缩后json数据长度 ---->" + zipStrVariety.length()); System.out.println("压缩后 原始结构长度:变种数据结构="+((float)gzipStr.length())/(float)gzipStrVariety.length()); System.out.println("==================================================="); }*/ float repetitionRatio = 0.00F; List<Person> l = new ArrayList<Person>(); for(repetitionRatio = 0.000F; repetitionRatio < 0.500F; repetitionRatio+=0.005F){ int reportIndex = (int) (6000 * (1-repetitionRatio)); for(int i = 0;i<reportIndex;i++){ Person p = new Person(); p.age = i; p.gender = "gender"+i; p.name = "name"+i; l.add(p); } if(repetitionRatio > 0.00F){ int reportCount = (int) (6000 * repetitionRatio); for(int i = 0;i<reportCount;i++){ Person p = new Person(); p.age = i; p.gender = "gender"+i; p.name = "name"+i; l.add(p); } } Gson gson = new Gson(); List<String> names = new ArrayList<String>(); List<String> genders = new ArrayList<String>(); List<Integer> ages = new ArrayList<Integer>(); for(Person p:l){ names.add(p.name); genders.add(p.gender); ages.add(p.age); } PersonItemList itemList = new PersonItemList(); itemList.items = l; String jsonDataOri = gson.toJson(itemList); System.out.println("==================================================="); System.out.println("原始数据结构 压缩前json数据长度 ---->" + jsonDataOri.length()); PersonAttrList attrList = new PersonAttrList(); attrList.names = names; attrList.genders = genders; attrList.ages = ages; String jsonDataVariety = gson.toJson(attrList); System.out.println("变种数据结构 压缩前json数据长度 ---->" + jsonDataVariety.length()); //1:原始数据结构 //Gzip压缩 long start = System.currentTimeMillis(); String gzipStr = ZipUtils.compressForGzip(jsonDataOri); long end = System.currentTimeMillis(); System.out.println("原始数据结构 Gzip压缩后json数据长度 ---->" + gzipStr.length()); //2:变种数据结构 //Gzip压缩 start = System.currentTimeMillis(); String gzipStrVariety = ZipUtils.compressForGzip(jsonDataVariety); end = System.currentTimeMillis(); System.out.println("变种数据结构 Gzip压缩后json数据长度 ---->" + gzipStrVariety.length()); System.out.println("重复率为 "+repetitionRatio/(1-repetitionRatio)+" 压缩后:原始结构长度:变种数据结构="+((float)gzipStr.length())/(float)gzipStrVariety.length()); } } public class Person implements Serializable{ public String name; public String gender; public int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class PersonItemList implements Serializable{ public List<Person> items; public List<Person> getItems() { return items; } public void setItems(List<Person> items) { this.items = items; } } public class PersonAttrList implements Serializable{ public List<String> names; public List<String> genders; public List<Integer> ages; public List<String> getNames() { return names; } public void setNames(List<String> names) { this.names = names; } public List<String> getGenders() { return genders; } public void setGenders(List<String> genders) { this.genders = genders; } public List<Integer> getAges() { return ages; } public void setAges(List<Integer> ages) { this.ages = ages; } } } 首先看当单个对象属性重复率超过100%的情况下打印结果: List<Person> l = new ArrayList<Person>(); for(int i=0;i<1;i++){ for(int j=0;j<6000;j++){ Person p = new Person(); p.age = j; p.gender = "gender"+j; p.name = "name"+j; l.add(p); } } 原始数据结构 压缩前json数据长度 ---->273011 //因为i和j变动,数据会略有变化 变种数据结构 压缩前json数据长度 ---->129032 //因为i和j变动,数据会略有变化 i=x; j=y; //x=1,j=6000:代表数据没有任何重复的情形 x=1; j=6000; 原始数据结构 Gzip压缩后json数据长度 ---->44215 变种数据结构 Gzip压缩后json数据长度 ---->39561 压缩后 原始结构长度:变种数据结构=1.1176411 //x=2,j=3000:代表每个对象都存在另1个属性完全一致的对象.单个对象重复率100% x=2; j=3000; 原始数据结构 Gzip压缩后json数据长度 ---->44204 变种数据结构 Gzip压缩后json数据长度 ---->27628 压缩后 原始结构长度:变种数据结构=1.599971 //余下的代表每单个对象重复率超过100%的情况 x=3; j=2000; 原始数据结构 Gzip压缩后json数据长度 ---->43733 变种数据结构 Gzip压缩后json数据长度 ---->17020 压缩后 原始结构长度:变种数据结构=2.5695064 x=4; j=1500; 原始数据结构 Gzip压缩后json数据长度 ---->43398 变种数据结构 Gzip压缩后json数据长度 ---->13914 压缩后 原始结构长度:变种数据结构=3.119017 x=6; j=1000; 原始数据结构 Gzip压缩后json数据长度 ---->42166 变种数据结构 Gzip压缩后json数据长度 ---->8016 压缩后 原始结构长度:变种数据结构=5.2602296 x=7; j=857; 原始数据结构 Gzip压缩后json数据长度 ---->41743 变种数据结构 Gzip压缩后json数据长度 ---->7024 压缩后 原始结构长度:变种数据结构=5.94291 x=8; j=750; 原始数据结构 Gzip压缩后json数据长度 ---->41561 变种数据结构 Gzip压缩后json数据长度 ---->6378 压缩后 原始结构长度:变种数据结构=6.516306 x=9; j=667; 原始数据结构 Gzip压缩后json数据长度 ---->41491 变种数据结构 Gzip压缩后json数据长度 ---->5870 压缩后 原始结构长度:变种数据结构=7.0683136 x=10; j=600; 原始数据结构 Gzip压缩后json数据长度 ---->7552 变种数据结构 Gzip压缩后json数据长度 ---->5503 压缩后 原始结构长度:变种数据结构=1.3723423 x=12; j=500; 原始数据结构 Gzip压缩后json数据长度 ---->6955 变种数据结构 Gzip压缩后json数据长度 ---->4962 压缩后 原始结构长度:变种数据结构=1.4016526 x=15; j=400; 原始数据结构 Gzip压缩后json数据长度 ---->6207 变种数据结构 Gzip压缩后json数据长度 ---->4179 压缩后 原始结构长度:变种数据结构=1.4852836 x=20; j=300; 原始数据结构 Gzip压缩后json数据长度 ---->5117 变种数据结构 Gzip压缩后json数据长度 ---->3576 压缩后 原始结构长度:变种数据结构=1.4309285 x=30; j=200; 原始数据结构 Gzip压缩后json数据长度 ---->4511 变种数据结构 Gzip压缩后json数据长度 ---->3156 压缩后 原始结构长度:变种数据结构=1.429341 x=40; j=150; 原始数据结构 Gzip压缩后json数据长度 ---->4359 变种数据结构 Gzip压缩后json数据长度 ---->3035 压缩后 原始结构长度:变种数据结构=1.4362438 x=60; j=100; 原始数据结构 Gzip压缩后json数据长度 ---->2832 变种数据结构 Gzip压缩后json数据长度 ---->1382 压缩后 原始结构长度:变种数据结构=2.049204 x=80; j=75; 原始数据结构 Gzip压缩后json数据长度 ---->2581 变种数据结构 Gzip压缩后json数据长度 ---->1217 压缩后 原始结构长度:变种数据结构=2.1207888 x=150; j=40; 原始数据结构 Gzip压缩后json数据长度 ---->1835 变种数据结构 Gzip压缩后json数据长度 ---->890 压缩后 原始结构长度:变种数据结构=2.0617979 x=200; j=30; 原始数据结构 Gzip压缩后json数据长度 ---->1744 变种数据结构 Gzip压缩后json数据长度 ---->797 压缩后 原始结构长度:变种数据结构=2.1882057 x=300; j=20; 原始数据结构 Gzip压缩后json数据长度 ---->1539 变种数据结构 Gzip压缩后json数据长度 ---->739 压缩后 原始结构长度:变种数据结构=2.082544 x=316; j=19; 原始数据结构 Gzip压缩后json数据长度 ---->1269 变种数据结构 Gzip压缩后json数据长度 ---->725 压缩后 原始结构长度:变种数据结构=1.7503449 x=400; j=15; 原始数据结构 Gzip压缩后json数据长度 ---->1488 变种数据结构 Gzip压缩后json数据长度 ---->662 压缩后 原始结构长度:变种数据结构=2.247734 x=500; j=12; 原始数据结构 Gzip压缩后json数据长度 ---->1453 变种数据结构 Gzip压缩后json数据长度 ---->563 压缩后 原始结构长度:变种数据结构=2.580817 x=600; j=10; 原始数据结构 Gzip压缩后json数据长度 ---->1044 变种数据结构 Gzip压缩后json数据长度 ---->573 压缩后 原始结构长度:变种数据结构=1.8219895 x=667; j=9; 原始数据结构 Gzip压缩后json数据长度 ---->1291 变种数据结构 Gzip压缩后json数据长度 ---->527 压缩后 原始结构长度:变种数据结构=2.4497154 x=750; j=8; 原始数据结构 Gzip压缩后json数据长度 ---->1155 变种数据结构 Gzip压缩后json数据长度 ---->520 压缩后 原始结构长度:变种数据结构=2.2211537 x=1000; j=6; 原始数据结构 Gzip压缩后json数据长度 ---->1269 变种数据结构 Gzip压缩后json数据长度 ---->429 压缩后 原始结构长度:变种数据结构=2.958042 x=1200; j=5; 原始数据结构 Gzip压缩后json数据长度 ---->1135 变种数据结构 Gzip压缩后json数据长度 ---->478 压缩后 原始结构长度:变种数据结构=2.374477 x=3000; j=2; 原始数据结构 Gzip压缩后json数据长度 ---->990 变种数据结构 Gzip压缩后json数据长度 ---->382 压缩后 原始结构长度:变种数据结构=2.591623 x=6000; j=1; 原始数据结构 Gzip压缩后json数据长度 ---->590 变种数据结构 Gzip压缩后json数据长度 ---->311 压缩后 原始结构长度:变种数据结构=1.897106 当每个对象属性重复率低于100%的情况下打印结果: =================================================== 原始数据结构 压缩前json数据长度 ---->314681 变种数据结构 压缩前json数据长度 ---->170702 原始数据结构 Gzip压缩后json数据长度 ---->44215 变种数据结构 Gzip压缩后json数据长度 ---->39561 重复率为 0.0 压缩后:原始结构长度:变种数据结构=1.1176411 =================================================== 原始数据结构 压缩前json数据长度 ---->629141 变种数据结构 压缩前json数据长度 ---->341162 原始数据结构 Gzip压缩后json数据长度 ---->88279 变种数据结构 Gzip压缩后json数据长度 ---->66875 重复率为 0.0050251256 压缩后:原始结构长度:变种数据结构=1.3200598 =================================================== 原始数据结构 压缩前json数据长度 ---->943421 变种数据结构 压缩前json数据长度 ---->511442 原始数据结构 Gzip压缩后json数据长度 ---->131892 变种数据结构 Gzip压缩后json数据长度 ---->90806 重复率为 0.01010101 压缩后:原始结构长度:变种数据结构=1.4524591 =================================================== 原始数据结构 压缩前json数据长度 ---->1257521 变种数据结构 压缩前json数据长度 ---->681542 原始数据结构 Gzip压缩后json数据长度 ---->175554 变种数据结构 Gzip压缩后json数据长度 ---->116973 重复率为 0.015228426 压缩后:原始结构长度:变种数据结构=1.5008079 =================================================== 原始数据结构 压缩前json数据长度 ---->1571501 变种数据结构 压缩前json数据长度 ---->851522 原始数据结构 Gzip压缩后json数据长度 ---->218945 变种数据结构 Gzip压缩后json数据长度 ---->142129 重复率为 0.020408163 压缩后:原始结构长度:变种数据结构=1.5404668 =================================================== 原始数据结构 压缩前json数据长度 ---->1885341 变种数据结构 压缩前json数据长度 ---->1021386 原始数据结构 Gzip压缩后json数据长度 ---->262306 变种数据结构 Gzip压缩后json数据长度 ---->168725 重复率为 0.025641024 压缩后:原始结构长度:变种数据结构=1.5546362 =================================================== 原始数据结构 压缩前json数据长度 ---->2199091 变种数据结构 压缩前json数据长度 ---->1191160 原始数据结构 Gzip压缩后json数据长度 ---->305678 变种数据结构 Gzip压缩后json数据长度 ---->191222 重复率为 0.030927831 压缩后:原始结构长度:变种数据结构=1.5985503 =================================================== 原始数据结构 压缩前json数据长度 ---->2512751 变种数据结构 压缩前json数据长度 ---->1360844 原始数据结构 Gzip压缩后json数据长度 ---->348774 变种数据结构 Gzip压缩后json数据长度 ---->219050 重复率为 0.036269426 压缩后:原始结构长度:变种数据结构=1.5922118 =================================================== 原始数据结构 压缩前json数据长度 ---->2826321 变种数据结构 压缩前json数据长度 ---->1530438 原始数据结构 Gzip压缩后json数据长度 ---->391506 变种数据结构 Gzip压缩后json数据长度 ---->243066 重复率为 0.041666664 压缩后:原始结构长度:变种数据结构=1.6106983 =================================================== 原始数据结构 压缩前json数据长度 ---->3139801 变种数据结构 压缩前json数据长度 ---->1699942 原始数据结构 Gzip压缩后json数据长度 ---->434274 变种数据结构 Gzip压缩后json数据长度 ---->268432 重复率为 0.047120415 压缩后:原始结构长度:变种数据结构=1.6178175 **** =================================================== 原始数据结构 压缩前json数据长度 ---->29936815 变种数据结构 压缩前json数据长度 ---->16114684 原始数据结构 Gzip压缩后json数据长度 ---->4187707 变种数据结构 Gzip压缩后json数据长度 ---->2014350 重复率为 0.9047608 压缩后:原始结构长度:变种数据结构=2.078937 =================================================== 原始数据结构 压缩前json数据长度 ---->30248102 变种数据结构 压缩前json数据长度 ---->16281995 原始数据结构 Gzip压缩后json数据长度 ---->4232504 变种数据结构 Gzip压缩后json数据长度 ---->2034384 重复率为 0.92307574 压缩后:原始结构长度:变种数据结构=2.0804844 =================================================== 原始数据结构 压缩前json数据长度 ---->30559389 变种数据结构 压缩前json数据长度 ---->16449306 原始数据结构 Gzip压缩后json数据长度 ---->4277046 变种数据结构 Gzip压缩后json数据长度 ---->2053854 重复率为 0.94174635 压缩后:原始结构长度:变种数据结构=2.082449 =================================================== 原始数据结构 压缩前json数据长度 ---->30870676 变种数据结构 压缩前json数据长度 ---->16616617 原始数据结构 Gzip压缩后json数据长度 ---->4321134 变种数据结构 Gzip压缩后json数据长度 ---->2072485 重复率为 0.960783 压缩后:原始结构长度:变种数据结构=2.0850012 =================================================== 原始数据结构 压缩前json数据长度 ---->31181963 变种数据结构 压缩前json数据长度 ---->16783928 原始数据结构 Gzip压缩后json数据长度 ---->4365924 变种数据结构 Gzip压缩后json数据长度 ---->2087159 重复率为 0.9801967 压缩后:原始结构长度:变种数据结构=2.0918024 =================================================== 原始数据结构 压缩前json数据长度 ---->31493250 变种数据结构 压缩前json数据长度 ---->16951239 原始数据结构 Gzip压缩后json数据长度 ---->4409476 变种数据结构 Gzip压缩后json数据长度 ---->2100664 重复率为 0.9999986 压缩后:原始结构长度:变种数据结构=2.0990868