阅读更多

0顶
0踩

移动开发

转载新闻 Android性能优化典范(三)

2015-03-04 14:33 by 副主编 mengyidan1988 评论(0) 有3125人浏览
Android性能优化典范(一)Android性能优化典范(二)
接上文:
9)Garbage Collection in Android

JVM的回收机制给开发人员带来很大的好处,不用时刻处理对象的分配与回收,可以更加专注于更加高级的代码实现。相比起Java,C与C++等语言具备更高的执行效率,他们需要开发人员自己关注对象的分配与回收,但是在一个庞大的系统当中,还是免不了经常发生部分对象忘记回收的情况,这就是内存泄漏。

原始JVM中的GC机制在Android中得到了很大程度上的优化。Android里面是一个三级Generation的内存模型,最近分配的对象会存放在Young Generation区域,当这个对象在这个区域停留的时间达到一定程度,它会被移动到Old Generation,最后到Permanent Generation区域。



每一个级别的内存区域都有固定的大小,此后不断有新的对象被分配到此区域,当这些对象总的大小快达到这一级别内存区域的阀值时,会触发GC的操作,以便腾出空间来存放其他新的对象。



前面提到过每次GC发生的时候,所有的线程都是暂停状态的。GC所占用的时间和它是哪一个Generation也有关系,Young Generation的每次GC操作时间是最短的,Old Generation其次,Permanent Generation最长。执行时间的长短也和当前Generation中的对象数量有关,遍历查找20000个对象比起遍历50个对象自然是要慢很多的。

虽然Google的工程师在尽量缩短每次GC所花费的时间,但是特别注意GC引起的性能问题还是很有必要。如果不小心在最小的for循环单元里面执行了创建对象的操作,这将很容易引起GC并导致性能问题。通过Memory Monitor我们可以查看到内存的占用情况,每一次瞬间的内存降低都是因为此时发生了GC操作,如果在短时间内发生大量的内存上涨与降低的事件,这说明很有可能这里有性能问题。我们还可以通过Heap and Allocation Tracker工具来查看此时内存中分配的到底有哪些对象。

10)Performance Cost of Memory Leaks

虽然Java有自动回收的机制,可是这不意味着Java中不存在内存泄漏的问题,而内存泄漏会很容易导致严重的性能问题。

内存泄漏指的是那些程序不再使用的对象无法被GC识别,这样就导致这个对象一直留在内存当中,占用了宝贵的内存空间。显然,这还使得每级Generation的内存区域可用空间变小,GC就会更容易被触发,从而引起性能问题。

寻找内存泄漏并修复这个漏洞是件很棘手的事情,你需要对执行的代码很熟悉,清楚的知道在特定环境下是如何运行的,然后仔细排查。例如,你想知道程序中的某个activity退出的时候,它之前所占用的内存是否有完整的释放干净了?首先你需要在activity处于前台的时候使用Heap Tool获取一份当前状态的内存快照,然后你需要创建一个几乎不这么占用内存的空白activity用来给前一个Activity进行跳转,其次在跳转到这个空白的activity的时候主动调用System.gc()方法来确保触发一个GC操作。最后,如果前面这个activity的内存都有全部正确释放,那么在空白activity被启动之后的内存快照中应该不会有前面那个activity中的任何对象了。



如果你发现在空白activity的内存快照中有一些可疑的没有被释放的对象存在,那么接下去就应该使用Alocation Track Tool来仔细查找具体的可疑对象。我们可以从空白activity开始监听,启动到观察activity,然后再回到空白activity结束监听。这样操作以后,我们可以仔细观察那些对象,找出内存泄漏的真凶。



11)Memory Performance

通常来说,Android对GC做了大量的优化操作,虽然执行GC操作的时候会暂停其他任务,可是大多数情况下,GC操作还是相对很安静并且高效的。但是如果我们对内存的使用不恰当,导致GC频繁执行,这样就会引起不小的性能问题。

为了寻找内存的性能问题,Android Studio提供了工具来帮助开发者。
  • Memory Monitor:查看整个app所占用的内存,以及发生GC的时刻,短时间内发生大量的GC操作是一个危险的信号。
  • Allocation Tracker:使用此工具来追踪内存的分配,前面有提到过。
  • Heap Tool:查看当前内存快照,便于对比分析哪些对象有可能是泄漏了的,请参考前面的Case。

12)Tool - Memory Monitor

Android Studio中的Memory Monitor可以很好的帮组我们查看程序的内存使用情况。









13)Battery Performance

电量其实是目前手持设备最宝贵的资源之一,大多数设备都需要不断的充电来维持继续使用。不幸的是,对于开发者来说,电量优化是他们最后才会考虑的的事情。但是可以确定的是,千万不能让你的应用成为消耗电量的大户。

Purdue University研究了最受欢迎的一些应用的电量消耗,平均只有30%左右的电量是被程序最核心的方法例如绘制图片,摆放布局等等所使用掉的,剩下的70%左右的电量是被上报数据,检查位置信息,定时检索后台广告信息所使用掉的。如何平衡这两者的电量消耗,就显得非常重要了。

有下面一些措施能够显著减少电量的消耗:

我们应该尽量减少唤醒屏幕的次数与持续的时间,使用WakeLock来处理唤醒的问题,能够正确执行唤醒操作并根据设定及时关闭操作进入睡眠状态。
某些非必须马上执行的操作,例如上传歌曲,图片处理等,可以等到设备处于充电状态或者电量充足的时候才进行。
触发网络请求的操作,每次都会保持无线信号持续一段时间,我们可以把零散的网络请求打包进行一次操作,避免过多的无线信号引起的电量消耗。关于网络请求引起无线信号的电量消耗,还可以参考这里http://hukai.me/android-training-course-in-chinese/connectivity/efficient-downloads/efficient-network-access.html
我们可以通过手机设置选项找到对应App的电量消耗统计数据。我们还可以通过Battery Historian Tool来查看详细的电量消耗。



如果发现我们的App有电量消耗过多的问题,我们可以使用JobScheduler API来对一些任务进行定时处理,例如我们可以把那些任务重的操作等到手机处于充电状态,或者是连接到WiFi的时候来处理。 关于JobScheduler的更多知识可以参考http://hukai.me/android-training-course-in-chinese/background-jobs/scheduling/index.html

14)Understanding Battery Drain on Android

电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情。唯一可行的方案是使用第三方监测电量的设备,这样才能够获取到真实的电量消耗。

当设备处于待机状态时消耗的电量是极少的,以N5为例,打开飞行模式,可以待机接近1个月。可是点亮屏幕,硬件各个模块就需要开始工作,这会需要消耗很多电量。

使用WakeLock或者JobScheduler唤醒设备处理定时的任务之后,一定要及时让设备回到初始状态。每次唤醒无线信号进行数据传递,都会消耗很多电量,它比WiFi等操作更加的耗电,详情请关注http://hukai.me/android-training-course-in-chinese/connectivity/efficient-downloads/efficient-network-access.html



修复电量的消耗是另外一个很大的课题,这里就不展开继续了。

15)Battery Drain and WakeLocks

高效的保留更多的电量与不断促使用户使用你的App来消耗电量,这是矛盾的选择题。不过我们可以使用一些更好的办法来平衡两者。

假设你的手机里面装了大量的社交类应用,即使手机处于待机状态,也会经常被这些应用唤醒用来检查同步新的数据信息。Android会不断关闭各种硬件来延长手机的待机时间,首先屏幕会逐渐变暗直至关闭,然后CPU进入睡眠,这一切操作都是为了节约宝贵的电量资源。但是即使在这种睡眠状态下,大多数应用还是会尝试进行工作,他们将不断的唤醒手机。一个最简单的唤醒手机的方法是使用PowerManager.WakeLock的API来保持CPU工作并防止屏幕变暗关闭。这使得手机可以被唤醒,执行工作,然后回到睡眠状态。知道如何获取WakeLock是简单的,可是及时释放WakeLock也是非常重要的,不恰当的使用WakeLock会导致严重错误。例如网络请求的数据返回时间不确定,导致本来只需要10s的事情一直等待了1个小时,这样会使得电量白白浪费了。这也是为何使用带超时参数的wakelock.acquice()方法是很关键的。但是仅仅设置超时并不足够解决问题,例如设置多长的超时比较合适?什么时候进行重试等等?

解决上面的问题,正确的方式可能是使用非精准定时器。通常情况下,我们会设定一个时间进行某个操作,但是动态修改这个时间也许会更好。例如,如果有另外一个程序需要比你设定的时间晚5分钟唤醒,最好能够等到那个时候,两个任务捆绑一起同时进行,这就是非精确定时器的核心工作原理。我们可以定制计划的任务,可是系统如果检测到一个更好的时间,它可以推迟你的任务,以节省电量消耗。



这正是JobScheduler API所做的事情。它会根据当前的情况与任务,组合出理想的唤醒时间,例如等到正在充电或者连接到WiFi的时候,或者集中任务一起执行。我们可以通过这个API实现很多免费的调度算法。

从Android 5.0开始发布了Battery History Tool,它可以查看程序被唤醒的频率,又谁唤醒的,持续了多长的时间,这些信息都可以获取到。

请关注程序的电量消耗,用户可以通过手机的设置选项观察到那些耗电量大户,并可能决定卸载他们。所以尽量减少程序的电量消耗是非常有必要的。

来自:胡凯的博客
  • 大小: 69.4 KB
  • 大小: 73.8 KB
  • 大小: 135.2 KB
  • 大小: 192.3 KB
  • 大小: 64.5 KB
  • 大小: 74.2 KB
  • 大小: 66.7 KB
  • 大小: 99.6 KB
  • 大小: 153.4 KB
  • 大小: 73 KB
来自: 胡凯的博客
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java语言发送邮件

    * 发送邮件,发到所有邮件的收件地址,message.getAllRecipients()获取到的是创建邮件对象时添加的所有邮件人,抄送人,密送人。* 发件人的SMTP服务器地址,必须准确,不同邮件服务器地址不同,一般(只是一般,不是...

  • 利用java发送邮件时在正文中加表格

    发送邮件时直接以附件的形式附上一个excel表格没什么问题,用poi包里的函数和类就可以操作excel表格了,但是直接画的时候就比较复杂,需要类似于写html文件一样写出来。 StringBuilder content = new StringBuilder...

  • Java发送邮件详解

    一、关于电子邮件 电子邮件 传输协议 SMTP协议 POP3协议 邮件收发原理 二、发送纯文本邮件 二、发送带图片和附件的邮件 一、关于电子邮件 电子邮件 要在网络上实现邮件功能,必须要有专门的邮件服务器。 ...

  • java 邮件发送_Java 基于JavaMail的邮件发送

    http://blog.csdn.net/xietansheng/article/details/51673073http://blog.csdn.net/xietansheng/article/details/51722660电子邮件的应用非常广泛,例如在某网站注册了一个账户,自动发送一封欢迎邮件,通过邮件找回...

  • Java后端邮件发送

    使用SpringBoot发送邮件,搭建环境非常容易,首先在创建项目时添加邮件依赖,代码如下: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId&gt...

  • Java邮件发送详解

    电子邮件 要在网络上实现邮件功能,必须要有专门的邮件服务器。 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。 SMTP服务器地址:一般是 smtp....

  • java发送邮件354_基于SMTP的JAVA邮件发送程序

    这个程序没有使用JavaMail API,而是根据SMTP协议的要求直接处理协议的细节发送邮件,虽然比较麻烦了一些,但是对了解邮件协议的细节很有帮助的。本文分两部分,第一部分是SMTP命令介绍(这个从别的地方抄的,嘿嘿);...

  • java 邮件 并发发送,java – 并发电子邮件处理(不发送垃圾邮件)

    如果存在异常,则必须将电子邮件发送给具有检测到的异常的一群人.然而,为了避免垃圾邮件(csv有时可能是几十万行),我必须保持X秒的阈值.如果从同一条件(来自正在模拟的同一设备)发送相同异常的邮件< X秒回来,我必须...

  • java发送gmail邮件_如何安排在Gmail中发送电子邮件

    java发送gmail邮件Alexey Boldin/Shutterstock阿列克谢·博尔丁/快门 Gmail now lets you write an email and schedule a sending time. Schedule an email for later, and it will go out at the specific date and...

  • java发送电子邮件

    java发送电子邮件,简单方便易操作。

  • 网易云邮箱发送邮件 java

    网易云邮箱发送邮件 java

  • Java发送邮件时标题和发件人乱码

    最近碰到一个问题,Java发送邮件时,

  • java邮件接收_Java邮件发送与接收原理

    一、邮件开发涉及到的一些基本概念1.1、邮件服务器和电子邮箱要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163等等他们都有自己的邮件服务器...

  • java邮件发送

    邮箱服务器:主要是用于接收并转发邮件,类似于邮局,把用户的邮件接收过来,然后转 发到邮件接收者的电子邮箱中。 服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。 邮箱...

  • JAVA发送邮件的3个实例

    引入 javamail 发送一封简单邮件

  • java邮件中添加excel_Java以邮件附件的方式发送excel文件

    思路:Java创建Excel,返回一个... sendEmail()接受ByteArrayOutputStream 流以附件的形式发送出去创建Excel表格:public class CreatExcel {public static ByteArrayOutputStream creatExcel(String[] title, JS...

  • java 发送邮件 详解

    SMTP : 简单邮件传输协议,用于发送电子邮件的传输协议 POP3 : 用于接收电子邮件的标准协议 IMAP : 互联网消息访问协议,是 POP3 的替代协议 这三种协议都有对应 SSL 加密传输的协议,分别是 SMTPS、 POP3S 和 ...

  • java邮箱发送不出去_java mail问题,邮件发不出去,请教高手!!!!!!

    我的程序代码如下:importjavax.mail.internet.InternetAddress;...importjava.util.Properties;importjavax.mail.Session;importjava.io.FileOu...我的程序代码如下:import javax.mail.internet....

  • java+电子邮件工具_Java发送邮件工具类

    package mes.report....import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;im...

  • Java发送电子邮件

    package ... import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.FileDataS...

Global site tag (gtag.js) - Google Analytics