Android性能优化 中
7.Android性能优化典范-第4季
5.数据呈现的顺序以及结构会对序列化之后的空间产生不小的影响
改变数据结构对内存及gzip的影响
- 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不受影响
- okHttp支持gzip自动解压缩,不需要设置Accept-Encoding为gzip
- gzip概念:HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术
- 我们在向服务器提交大量数据的时候,希望对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();
2.改变数据结构,就是将原始集合按照集合中对象的属性进行拆分,变成多个属性集合的形式.
- 改变数据结构后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 l = new ArrayList();
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 names = new ArrayList();
List genders = new ArrayList();
List ages = new ArrayList();
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" + (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 l = new ArrayList();
for(repetitionRatio = 0.000F; repetitionRatio < 0.500F; repetitionRatio+=0.005F){
int reportIndex = (int) (6000 * (1-repetitionRatio));
for(int i = 0;i 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 names = new ArrayList();
List genders = new ArrayList();
List ages = new ArrayList();
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 items;
public List getItems() {
return items;
}
public void setItems(List items) {
this.items = items;
}
}
public class PersonAttrList implements Serializable{
public List names;
public List genders;
public List ages;
public List getNames() {
return names;
}
public void setNames(List names) {
this.names = names;
}
public List getGenders() {
return genders;
}
public void setGenders(List genders) {
this.genders = genders;
}
public List getAges() {
return ages;
}
public void setAges(List ages) {
this.ages = ages;
}
}
}
首先看当单个对象属性重复率超过100%的情况下打印结果:
List l = new ArrayList();
for(int i=0;i<1;i++){
for(int j=0;j273011 //因为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