7.Android性能优化典范-第4季
5.数据呈现的顺序以及结构会对序列化之后的空间产生不小的影响
改变数据结构对内存及gzip的影响
gzip
一般对纯文本内容可压缩到原大小的40%
减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间
okHttp支持gzip自动解压缩,不需要设置Accept-Encoding为gzip
我们在向服务器提交大量数据的时候,希望对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();
自动解压时移除Content-Length,所以上层Java代码想要contentLength时为-1
自动解压时移除 Content-Encoding
自动解压时,如果是分块传输编码,Transfer-Encoding: chunked不受影响
开发者手动设置Accept-Encoding,okHttp不负责解压缩
开发者没有设置Accept-Encoding时,则自动添加Accept-Encoding: gzip,自动添加的request,response支持自动解压
gzip概念:HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术
okHttp对gzip的支持
改变数据结构,就是将原始集合按照集合中对象的属性进行拆分,变成多个属性集合的形式.
改变数据结构后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.5695064x=4; j=1500; 原始数据结构 Gzip压缩后json数据长度 ---->43398变种数据结构 Gzip压缩后json数据长度 ---->13914压缩后 原始结构长度:变种数据结构=3.119017x=6; j=1000; 原始数据结构 Gzip压缩后json数据长度 ---->42166变种数据结构 Gzip压缩后json数据长度 ---->8016压缩后 原始结构长度:变种数据结构=5.2602296x=7; j=857; 原始数据结构 Gzip压缩后json数据长度 ---->41743变种数据结构 Gzip压缩后json数据长度 ---->7024压缩后 原始结构长度:变种数据结构=5.94291x=8; j=750; 原始数据结构 Gzip压缩后json数据长度 ---->41561变种数据结构 Gzip压缩后json数据长度 ---->6378压缩后 原始结构长度:变种数据结构=6.516306x=9; j=667; 原始数据结构 Gzip压缩后json数据长度 ---->41491变种数据结构 Gzip压缩后json数据长度 ---->5870压缩后 原始结构长度:变种数据结构=7.0683136x=10; j=600; 原始数据结构 Gzip压缩后json数据长度 ---->7552变种数据结构 Gzip压缩后json数据长度 ---->5503压缩后 原始结构长度:变种数据结构=1.3723423x=12; j=500; 原始数据结构 Gzip压缩后json数据长度 ---->6955变种数据结构 Gzip压缩后json数据长度 ---->4962压缩后 原始结构长度:变种数据结构=1.4016526x=15; j=400; 原始数据结构 Gzip压缩后json数据长度 ---->6207变种数据结构 Gzip压缩后json数据长度 ---->4179压缩后 原始结构长度:变种数据结构=1.4852836x=20; j=300; 原始数据结构 Gzip压缩后json数据长度 ---->5117变种数据结构 Gzip压缩后json数据长度 ---->3576压缩后 原始结构长度:变种数据结构=1.4309285x=30; j=200; 原始数据结构 Gzip压缩后json数据长度 ---->4511变种数据结构 Gzip压缩后json数据长度 ---->3156压缩后 原始结构长度:变种数据结构=1.429341x=40; j=150; 原始数据结构 Gzip压缩后json数据长度 ---->4359变种数据结构 Gzip压缩后json数据长度 ---->3035压缩后 原始结构长度:变种数据结构=1.4362438x=60; j=100; 原始数据结构 Gzip压缩后json数据长度 ---->2832变种数据结构 Gzip压缩后json数据长度 ---->1382压缩后 原始结构长度:变种数据结构=2.049204x=80; j=75; 原始数据结构 Gzip压缩后json数据长度 ---->2581变种数据结构 Gzip压缩后json数据长度 ---->1217压缩后 原始结构长度:变种数据结构=2.1207888x=150; j=40; 原始数据结构 Gzip压缩后json数据长度 ---->1835变种数据结构 Gzip压缩后json数据长度 ---->890压缩后 原始结构长度:变种数据结构=2.0617979x=200; j=30; 原始数据结构 Gzip压缩后json数据长度 ---->1744变种数据结构 Gzip压缩后json数据长度 ---->797压缩后 原始结构长度:变种数据结构=2.1882057x=300; j=20; 原始数据结构 Gzip压缩后json数据长度 ---->1539变种数据结构 Gzip压缩后json数据长度 ---->739压缩后 原始结构长度:变种数据结构=2.082544x=316; j=19; 原始数据结构 Gzip压缩后json数据长度 ---->1269变种数据结构 Gzip压缩后json数据长度 ---->725压缩后 原始结构长度:变种数据结构=1.7503449x=400; j=15; 原始数据结构 Gzip压缩后json数据长度 ---->1488变种数据结构 Gzip压缩后json数据长度 ---->662压缩后 原始结构长度:变种数据结构=2.247734x=500; j=12; 原始数据结构 Gzip压缩后json数据长度 ---->1453变种数据结构 Gzip压缩后json数据长度 ---->563压缩后 原始结构长度:变种数据结构=2.580817x=600; j=10; 原始数据结构 Gzip压缩后json数据长度 ---->1044变种数据结构 Gzip压缩后json数据长度 ---->573压缩后 原始结构长度:变种数据结构=1.8219895x=667; j=9; 原始数据结构 Gzip压缩后json数据长度 ---->1291变种数据结构 Gzip压缩后json数据长度 ---->527压缩后 原始结构长度:变种数据结构=2.4497154x=750; j=8; 原始数据结构 Gzip压缩后json数据长度 ---->1155变种数据结构 Gzip压缩后json数据长度 ---->520压缩后 原始结构长度:变种数据结构=2.2211537x=1000; j=6; 原始数据结构 Gzip压缩后json数据长度 ---->1269变种数据结构 Gzip压缩后json数据长度 ---->429压缩后 原始结构长度:变种数据结构=2.958042x=1200; j=5; 原始数据结构 Gzip压缩后json数据长度 ---->1135变种数据结构 Gzip压缩后json数据长度 ---->478压缩后 原始结构长度:变种数据结构=2.374477x=3000; j=2; 原始数据结构 Gzip压缩后json数据长度 ---->990变种数据结构 Gzip压缩后json数据长度 ---->382压缩后 原始结构长度:变种数据结构=2.591623x=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
作者:幻海流心
链接:https://www.jianshu.com/p/ded89dd6f43f
共同学习,写下你的评论
评论加载中...
作者其他优质文章