对于GC这个近乎玄学的东西一直是感觉神龙见首不见尾,看得见但是摸不着,Monitor里面每次都有它,一切看起来都似乎是理所当然地进行着,对GC的印象还是一直停留在一个自动运转的垃圾回收器默默地帮我处理好了关于内存分配和回收的一切,虽然事实上GC的作用就是这些,但是当碰到界面卡顿的时候不得不怀疑是过于频繁地GC所造成的。

1.数据库:怪我咯?

我们知道,一切涉及到数据库的操作都比较耗费系统的性能,因为实质上它是一个不断I/O的过程,始终伴随着变量的生成和回收,所以操作过于频繁的时候或者当数据库过于庞大的时候这个过程就会因为过于频繁地GC而造成界面卡顿。

2.实例分析

需求:用户点击查询某一天的历史数据信息,判断本地数据库中是否存在数据:

List datalogs = DataSupport.findAll(Datalog.class);

if (datalogs.size() > 0){

//TODO

}

继续看findAll()源码,发现是个同步锁方法

public static synchronized List findAll(Class modelClass, long... ids) {

return findAll(modelClass, false, ids);

}

public static synchronized List findAll(Class modelClass, boolean isEager,

long... ids) {

QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());

return queryHandler.onFindAll(modelClass, isEager, ids);

}

List onFindAll(Class modelClass, boolean isEager, long... ids) {

List dataList;

if (isAffectAllLines(ids)) {

dataList = query(modelClass, null, null, null, null, null, "id", null,

getForeignKeyAssociations(modelClass.getName(), isEager));

} else {

dataList = query(modelClass, null, getWhereOfIdsWithOr(ids), null, null, null, "id",

null, getForeignKeyAssociations(modelClass.getName(), isEager));

}

return dataList;

}

这边是通过query()来返回一个数据集合。

if (cursor.moveToFirst()) {

SparseArray queryInfoCacheSparseArray = new SparseArray();

Map genericModelMap = new HashMap();

do {

T modelInstance = (T) createInstanceFromClass(modelClass);

giveBaseObjIdValue((DataSupport) modelInstance,

cursor.getLong(cursor.getColumnIndexOrThrow("id")));

setValueToModel(modelInstance, supportedFields, foreignKeyAssociations, cursor, queryInfoCacheSparseArray);

setGenericValueToModel((DataSupport) modelInstance, supportedGenericFields, genericModelMap);

if (foreignKeyAssociations != null) {

setAssociatedModel((DataSupport) modelInstance);

}

dataList.add(modelInstance);

} while (cursor.moveToNext());

queryInfoCacheSparseArray.clear();

genericModelMap.clear();

}

可见整个数据库操作的时间和数据库的大小也就是数据量是有直接关系的,有几条数据就会产生几个数据单例,当数据量过大的时候就会造成由于频繁地GC而造成的界面卡顿效果,下面Monitor调试监控情况:

logcat

Monitors

很明显,在用户点击查询之后由于进行了多达8次的GC过程,CPU地使用率一度高达50%,在ANR的边缘不断试探,界面在短时间内处于不可操作的状态,加载对话框也无法正常显示,用户体验这时候是极差的,由源码我们知道就是因为在初始化dataList的时候由于数据量过于庞大造成的频繁GC的结果。

简而言之, 就是执行GC操作的时候,任何线程的任何操作都会需要暂停,等待GC操作完成之后,其他操作才能够继续运行, 故而如果程序频繁GC, 自然会导致界面卡顿。

3.解决方法

由于在历史数据库中只存在某一天的数据,所以在判断数据中是否存在被查询的数据时是需要查询数据库中的第一条数据的时间是否符合要求:

/*

取得数据库第一条数据的年月日

*/

Datalog firstLog = DataSupport.findFirst(Datalog.class);

if (firstLog != null){

String time = firstLog.getDtime();

String checkTime = time.substring(0,8);

if (date.substring(2,10).equals(checkTime)){

Log.d("初始化阶段","搜索数据库");

/*

读数据库,显示数据

*/

new Thread(new Runnable() {

@Override

public void run() {

searchAndShowData();

}

}).start();

}else {

Log.d("初始化阶段","无该日数据-请求服务器");

DataSupport.deleteAll(Datalog.class);

//解析用户输入的年月日

parseAndQueryServer(date);

}

}else {

//解析用户输入的年月日

Log.d("初始化阶段","无数据-请求服务器");

DataSupport.deleteAll(Datalog.class);

parseAndQueryServer(date);

}

T onFindFirst(Class modelClass, boolean isEager) {

List dataList = query(modelClass, null, null, null, null, null, "id", "1",

getForeignKeyAssociations(modelClass.getName(), isEager));

if (dataList.size() > 0) {

return dataList.get(0);

}

return null;

}

在onFindFirst()方法里只需要查询一条数据,这就意味着while只会循环一次,大大减少了GC的时间和次数。

改进之后的效果:

logcat

GC只进行了一次,界面卡顿问题完美解决。

android gc卡顿,由于频繁GC造成的界面卡顿原因分析相关推荐

  1. 生产故障|Kafka ISR频繁伸缩缩引发性能急剧下降原因分析

    本文是笔者双十一系列第二弹,源于一个双十一期间一个让笔者猝不及防的生产故障,本文将详细剖析Kafka的副本机制,以及ISR频繁变更(扩张与伸缩)为什么会导致集群不可用. 1.Kafka副本机制 Kaf ...

  2. 对于ANDROID 5.0及其以上版本WIFI图标上显示感叹号的原因分析及解决方法

    这里我指的是WIFI可正常连接网络使用的前提下,手机状态栏WIF图标上仍出现感叹号的情况. 原因: 从 Android 5.0 开始,当安卓系统连接网络时,系统会向Google的某个特定的网址(htt ...

  3. Linux不讲武德——开机无法进入登录界面 卡在进度条就不动了

    目录 问题描述 原因分析 问题排查步骤 1.重启进入单用户模式 2.进入到内核参数修改界面 3.修改内核参数 4.单用户模式界面 5.排查/etc/inittab配置文件 6.排查相关服务 我们发现 ...

  4. Android面试系列文章2018之内存管理之UI卡顿篇

    Android面试系列文章2018之内存管理之UI卡顿篇 1.UI卡顿的原理   60ftp –> 16ms: Android系统每隔16ms都会对界面进行渲染一次,造成卡顿的原因就是Andro ...

  5. Android中app卡顿原因分析示例

    http://www.cnblogs.com/zhucai/p/weibo-graphics-performance-analyse.html 朱才 专注于Android图形动画 MIUI工程师 博客 ...

  6. 什么情况下会发生full Gc?如何排查频繁发生full Gc的原因?

    GC就是Java的垃圾回收机制,要了解什么情况下会发生GC(即GC得触发条件),我们需要先了解JVM的内存模型结构,之前一篇文章已经详细讲解了Jvm的内存模型结构,而通常来说,GC主要针对的是堆(ja ...

  7. 线上频繁GC怎么处理

    1.故障突发 频繁GC会导致接口变慢,系统明显卡顿.首先当然是以最快的速度恢复系统的正常使用,然后组织相关干系人进行快速决策会议,进行事故原因排查,定位问题的根本原因. 2.故障恢复 1.先查看是否是 ...

  8. Android主线程耗时动画卡顿,Android性能优化实战之界面卡顿

    原标题:Android性能优化实战之界面卡顿 作者:红橙Darren https://www.jianshu.com/p/18bb507d6e62 今天是个奇怪的日子,有三位同学找我,都是关于界面卡顿 ...

  9. android8卡顿,Android 8.0系统曝光,解决了安卓系统卡顿的问题

    原标题:Android 8.0系统曝光,解决了安卓系统卡顿的问题 8.0拟于今年5月17-19日召开的2017年谷歌I/O大会上正式宣布,之前已经曝光了该系统的一些特性,例如开发代号为奥利奥(Oero ...

  10. 线上环境频繁GC问题排查,Finalizer对象该背这个锅吗?

    问题描述 公司的一个SpringMVC服务,最近在做运维检查的时候发现young gc 和 full gc太频繁,远远超过了正常情况.服务器配置是4核8G,该服务分配了6G内存.通过arthas的da ...

最新文章

  1. 白话一下什么是决策树模型
  2. fillna函数_听说这些pandas函数,是数据科学家和软件工程师的最爱
  3. 【开学季限时免费】下载19880元大数据开发全链路教程(视频+源码)
  4. LaTeX中添加\usepackage{subfigure}一直报错的解决办法,亲测
  5. 荣耀20s真机谍照曝光:开孔全面屏+后置竖排三摄
  6. 听说你还不会写观察者模式?
  7. bpsk在瑞利信道matlab,请教BPSK在瑞利信道下的误码率仿真
  8. 蓝桥杯 明码题解 【Java实现】
  9. 全网首发 的Fiddler系列文章(二):Fiddler界面主菜单功能介绍
  10. Excel表格模板打包下载┆收集了各类各行业Excel表格、word模板
  11. u盘win7纯净版_如何制作纯净版WIN7启动U盘
  12. 使用QGIS插件转换火星坐标、百度坐标和WGS84坐标
  13. 手把手教你如何用Python从PDF文件中导出数据(附链接)
  14. 微信公众号模板消息推送(PHP)
  15. 现在的你迷茫吗?是否还在做毕业后的高薪梦?你相信彩虹海吗?
  16. 【Python3.6】生成微信好友个性签名词云
  17. WRL 类库项目模板
  18. 视频客服系统技术讨论
  19. Python 生成器里面的 return 有什么用?
  20. 从DDPM到GLIDE:基于扩散模型的图像生成算法进展

热门文章

  1. 风吹衣袖,月上西楼- 一个技术人员的心声
  2. win10查看激活时间(Win10查看激活信息)
  3. 词频统计 matlab,5年cvpr论文词频分析,今年最火词——深度学习
  4. 用户画像 客户喜好消费的商品分类模型表
  5. 科技风UI除了蓝色,还有什么配色选择?
  6. Excel小技巧-获取列数
  7. Codeforces 474B. Worms
  8. 世界上手机号码最长和最短的国家
  9. dell计算机的硬盘如何分区,dell电脑硬盘分区_dell电脑如何分区
  10. python毕业论文参考文献格式范例_毕业论文参考文献规范格式及例子