文档章节

高效实用内存

k
 kim366
发布于 2016/05/13 19:13
字数 2498
阅读 3
收藏 0
点赞 2
评论 0

         Android设备和其上应用使用的内存是有限的,使用尽可能少的内存,既是经验也是常识。此外,除了减少碰到OutOfMemoryError异常的风险,使用尽量少的内存也可以提升性能。

        性能主要取决于以下三个因素:

       1. CPU如何操作特定的数据类型。

       2. 数据和指令需要占用多少指令空间。

       3. 数据在内存中的布局。

  

        数据类型

        1.  使用较小的数据类型,并不总会提升性能,甚至可能需要更多的指令。所以在处理大量数据时,使用可以满足要求的最小的数据类型。

        2.  使用long看起来比使用short和int慢。同样,只使用double及混用float和double,似乎比只用float慢。

        3.  short数组排序远快于其他类型数组。(在不超过float取值范围-32768~32767的情况下,尽量使用short类型)。

        4.  处理64位类型(double或者float)比处理32位类型慢。

        5.  尽量避免类型转换。

        6.  如果有必要去的更好的性能,推倒重来,但要认真处理。

        这些规则不是一成不变的,但是,多半情况下,使用较少内存的原则是指的遵守的。此外,这样会留出更多的内存给其他的任务,使用较少的内存还可以提高性能,因为这样可以提高CPU缓存的使用率,更快地访问数据或者指令。


        访问内存

         因为访问内存会产生一些开销,CPU会把最近范文的内存内从缓存起来,无论是内存读还是内存写。事实上,CPU通常分为两级缓存:

                #  一级缓存(L1)

                #  二级缓存(L2)

         一级缓存通常比二级缓存快,但是比二级缓存小。例如,L1缓存可能是63kb(32kb数据缓存32kb指令缓存),而L2可能是512kb。(一些处理器可能还有三级缓存,通常几兆字节,但是目前的嵌入式设备上还没有)

        当数据或者指令在缓存中找不到时,就是缓存未命中。这时候需要从内存中去除数据或者指令。缓存命中有一下几种情况:

                 # 指令缓存读未命中

                 # 数据缓存读未命中

                 # 写未命中

        第一种缓存未命中最关键,因为CPU要一直等到从内存中读出指令,才可以继续执行。第二种缓存未命中几乎和第一种同样重要,尽管CPU仍可能执行其他不依赖要读取数据的指令,但这种情况只会在CPU指令乱序执行时出现。最后一种缓存未命中的重要性最低,CPU通常可以继续执行指令。你几乎无法控制写命中,不过无需过于担心,只要关心前两中类型就好,它两是应该激励避免的缓存命中情况。

         除了总大小,缓存的另一个重要的属性石其行大小。缓存由行组成,每行包含几个字节,如Contex A8的缓存行大小为64个字节(16个字)。缓存和缓存行背后的思想是局部性原则:如果应用读或者写入了一个特定的地址,将来很可能会再次读取或者写入到相同的地址或者非常邻近的地址。一下方法可以减少指令缓存未命中的几率:

        #  在Thumb模式下编译本地库。这不保证会使代码速度更快,因为Thumb指令码,比ARM指令码执行得慢(可能要执行更多的指令)。

        #  保持代码相对密集。 虽然不能保证密集的Java代码会产生密集的机器码,但是这往往是可行的。

        以下方法可以减少数据缓存的未命中率:

        #  在有大量数据存储在数组中时,使用尽量小的数据类型。

        # 选择顺序访问而不是随机访问。最大限度地重用已在缓存中的数据,防止数据从缓存清除后再次载入。

 

        排布数据

        1.  打破封装原则。尽管创建对象时轻量级的,但是内存分配还是会产生开销,而且这是不可避免的。如果属性是公有的,就可以避免getter方法的开销。

         这种原则可能带来维护上的问题,而不能正确地优化代码。因此要本着务实的态度来优化:在找到解决问题的关键点之前,不要优化,针对一种使用方式的优化,可能给其他使用方式带来劣化。         

        

         垃圾收集

        尽管Java可以自动进行垃圾回收,但是还是要注意:

         #  还是有可能出现内存泄露。

         #  垃圾收集会帮你管理内存(通过不同的垃圾收集器实现算法管理内存),它做的不仅仅是释放不用的内存。

 

         内存泄露

         只有当某个对象不再被引用时,它的内存才会被回收,当该被释放的对象应用依然存在时,就会发生内存泄露。在Android文档中看到的一个典型的例子是,由于屏幕旋转整个Activity对象会有泄露。这个典型的例子很容易重现,也是相当严重的,因为Activity对象占用相当多的内存(往往包含多个对象的应用)。避免内存泄露没有简单的解决方案,但Android提供的工具和API可以为你提供帮助。

         Eclipse中的DDMS视图中,可以用Heap和Allocation Tracker跟踪内存使用和分配情况,但这些工具是不会告诉你是否存在内存泄露的,你可以用他们来分析应用的内存使用情况。并有希望找出应用中的内存泄露。

         Android2.3中定义了StrictMode类,它对检测潜在的内存泄露有很大帮助。虽然在Android2.3中,StrictMode的虚拟机策略只能检测SQLite对象是否关闭是产生的泄露,但是在Android3.0及以上版本中,可以检测出一下潜在的泄露:

         #  Activity泄露;

         #  其他对象泄露;

         #  对象没有关闭造成的泄露(至于是哪些对象,可以查看文档中的Closeable接口的所有类);


        引用类型

        内存释放是垃圾收集器的一个重要的特性,在垃圾收集器中他的作用比在内存管理系统中重要的多。事实上,Java定义了四中类型的引用:

              #  强引用  ( Strong )

              #  软引用  ( Soft )

              #  弱引用  ( Weak )

              #  虚应用  ( Phantom )

         强引用: 程序中大部分都是用这种引用,强引用就是正常引用,简称为“引用”。

         软、弱、虚引用: 软引用和弱引用的本质是相似的,他们是没有抢到足以保持对象不被删除或回收的引用。不同之处在于回收时,垃圾收集器处理他们的对象的积极程度不同。

         软可及对象,既存在一个软引用,但是没有强引用,当有足够的内存保留对象时,垃圾收集器不会回收它。不过,如果垃圾收集器决定需要回收更多的内存,那么它可任意回收软可及对象的内存。这种引用适合于缓存,它可以自动删除缓存中的条目。

        弱可及对象,也就是说,存在一个弱引用,但没有强或者软引用,下次垃圾回收时基本上会被收走。换言之,垃圾收集器会更加积极地回收弱可及对象的内存。这种类型的引用适用于映射,这种映射可以自动删除不在被引用的键,WeakHashMap类就是这样做的。

        虚引用最弱,几乎很少用到。如果你的应用需要知道一个对象什么时候被回收,并需要在回收的同时执行一些清理工作,可以使用它们。虚引用够可以用来注册引用队列。

        软、弱、虚引用实际上是在对象本身和其他对象间加了一个间接层。

  

        垃圾收集

        垃圾收集可能会在不定的时间触发,你几乎无法控制它发生的时机。有时可以通过System.gc()提醒一下Android,但垃圾收集的发生时间最终由Dalvik虚拟机决定。有以下五种情况会触发垃圾收集:

        # GC_FOR_MALLOC : 发生在堆被占满,不能进行内存非配时,在分配新对象之前进行内存回收。

        # GC_CONCURRENT : 发生在(可能是部分的)垃圾可供回收时,通常有很多对象可以回收。

        # GC_EXPLICIT : 现实调用System.gc()产生的垃圾收集。

        # GC_EXTERENAL_ALLOC : Honeycomb及以上版本不会出现(一切都已在堆中分配)

        # GC_HPROF_DUMP_HEAP :  发生在创建HPROF文件时。

        在Android2.2或更早之前的版本中,垃圾收集发生在应用的主线程中,可能降低应用的响应速度和性能,造成恶劣影响。从Android2.3开始,有了转机,垃圾收集工作转移到了一个单独的线程进行。

    

        内存少的时候

        当内存不足以分配给所有程序的情况下,Android会要求应用及应用的组件(Activity,Fragment等)勒紧腰带。

        ComponentCallbacks接口定义了API onLowMemory(), 它对所有应用组件都是相同的。当它调用时,组件基本会被要求释放那些并不会用到的内存。通常情况下,onLowMemory()的实现将释放

        #  缓存或缓存条目(如使用强引用的LruCache);

        #  可以再次按需生成位图对象;

        #  不可见的布局对象;

        #  数据库对象;

        

本文转载自:http://blog.csdn.net/oyangyujun/article/details/47950025

共有 人打赏支持
k
粉丝 1
博文 129
码字总数 0
作品 0
朝阳
指针的魅力

指针的魅力 序 指针说:love me,love me! 但是他对指针说:I hate u,I hate u! …… 指针仅仅是作为指针,我们可以把它当做有用的工具,为我们提供便利与好处。说起工具不得不让我想起一...

zhanxinhang
2011/09/01
0
0
iBoxDB 2.8.3/2.17.3 发布,Java C# NoSQL 数据库

iBoxDB是一个实用高效的Java C#双核数据库,数据随时为可读状态,不受网络波动影响,不会出现连接突然断开或长时间等待导致几十秒的锁库。 内置的缓存层配合虚拟机的热点实时优化,访问次数越...

iBoxDB
07/12
0
0
网速精灵 v1.3 官方绿色版

网速精灵软件是一款实用的测网速软件。它网络速度直观,实时的在显示任务栏,信号条越多网速越好。绿色,免费,界面友好,高效,体积小,占用内存小。使用方法网速精灵使用很简单,打开软件后...

相心的泪
2016/08/31
10
0
企业信息系统开发平台--JBob

JBob是基于Java和Ajax的平台系统,采用Ext JS作为前端用户界面,Et-mvc作为后台支持框架,专注于权限控制,主要用于开发企业级信息系统。 平台集成了开发环境、运行框架,主要实现了用户组织...

jbob
2011/06/28
4.8K
0
[人工智能]机器学习的框架偏向于Python原因

前言 主要有以下原因: 1. Python是解释语言,程序写起来非常方便 写程序方便对做机器学习的人很重要。 因为经常需要对模型进行各种各样的修改,这在编译语言里很可能是牵一发而动全身的事情,...

baihuaxiu123
2017/01/11
0
0
ServiceFramework

ServiceFramework 适合你吗? ServcieFramework 定位在 移动互联网后端 领域。所以ServcieFramework非常强调开发的高效性,其开发效率可以比肩Rails(不相信?可以体验一下哦)。 拥有Java界最...

allwefantasy
2012/08/12
1K
1
开源的SIP协议栈--PJSIP

PJSIP是一个开放源代码的SIP协议栈。它支持多种SIP的扩展功能,目前可说算是最流行的sip协议栈之一了。 下面列出其重要的几种优点: 代码层次非常清晰,从低级到高级都提供了很方便的接口供开...

zhaohanyu
2010/10/18
16.5K
3
Pomer的网友评论

什么是 Pomer Pomer是一 个开源的企业信息管理系统基础框架,它提供了一系列企业信息管理系统的基础功能,包括企业组织架构管理,角色权限管理,菜单管理,数据权限控制等功能。 Pomer提供了...

红薯
2009/12/11
2.1K
4
轻量级 orm 开发框架 norm--.NET norm

norm 是一款轻巧,高效,实用的针对.NET开发的 orm ,它使用简单,大量语法参照 sql 语法,例如:OQL.From(model).Where(w => w.Compare(model.ID, "=", 388)).OrderBy(m => m.Asc(model.Crea......

wxd_tony1984
2016/02/04
2.3K
3
EasyFlash V1.04.20 发布,新增支持裸机及STM32F4平台

EasyFlash EasyFlash是一款开源的轻量级嵌入式Flash存储器库,主要为MCU(Micro Control Unit)提供便捷、通用的上层应用接口,使得开发者更加高效实现基于的Flash存储器常见应用开发。该库目前...

armink
2015/04/22
2.6K
7

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysqldump 用法

mysqldump 是文本备份还是二进制备份 它是文本备份,如果你打开备份文件你将看到所有的语句,可以用于重新创建表和对象。它也有 insert 语句来使用数据构成表。mysqldump 的语法是什么?...

郭恩洲_OSC博客
刚刚
0
0
我的第一个go web框架

使用了beego等go web开发框架之后,感觉各种不方便,尤其是在接收参数、和自定义输出的时候,各种难受,定义各种model,这不是找事情嘛??尤其是在角色权限控制的时候我也感觉力不从心。。。...

独坐苔痕但观罗敷
1分钟前
0
0
自动代码生成图形化工具

自动生成Spring代码 https://github.com/EliMirren/Spring-generator 自动生成Vertx https://gitee.com/duhua/vertx-generator...

奋斗的小牛
4分钟前
0
0
saltstack配置远程执行命令:

1.服务端配置 >>接着编辑之前的 top.sls 文件 # vim /srv/salt/top.sls //修改为如下 base: 'slaver.test.com': - cmdtest >>新建 cmdtest.sls 文件 # vim /srv/salt/cmdtest.sls cmd-test: ......

硅谷课堂
4分钟前
0
0
Signal处理中的函数可重入问题

1. Signal信号简介 信号是软件层次上模拟的中断,它是一种异步通信的处理机制。信号的异步性意味着,应用程序不用等待事件的发生,当信号发生时应用程序自动陷入到对应的信号处理函数中。产生...

pnsam301
6分钟前
0
0
小游戏开发初步

前阵子和朋友一起研究小程序开发,做了一些api单测之后,决定尝试开发一个小游戏试试。下面做个简单记录。 首先按照如下网址的教程,先申请了开发者账号 https://developers.weixin.qq.com/m...

propagator
7分钟前
0
0
mac配置redis单节点环境并启动服务

一、下载安装并启动redis服务 http://download.redis.io/releases/redis-4.0.10.tar.gz cd /Users/shijun/Desktop/openSourceProject/redis/sheep_redis-3.2.2 sudo make test sudo make in......

八戒八戒八戒
7分钟前
0
0
如何给容器服务的Docker增加数据盘

如何给容器服务的Docker增加数据盘 更新时间:2018-06-08 19:55:06 Docker的镜像存放目录修改与迁移(Ubuntu),https://my.oschina.net/u/2306127/blog/653569 Docker 的数据是通过联合文件...

openthings
7分钟前
0
0
Spring Cloud微服务架构代码结构详细讲解

上一篇我们介绍了spring cloud云服务架构 - particle云架构代码结构,简单的按照几个大的部分去构建代码模块,让我们来回顾一下: 第一部分: 针对于普通服务的基础框架封装(entity、dao、s...

itcloud
8分钟前
0
0
php 的 echo,print,print_r(),var_dump(),return 的区别

echo 输出一个或多个字符串,多个值直接用逗号分隔,它不是一个函数(它是一个语言结构), 因此你不一定要使用小括号来指明参数,单引号,双引号都可以. print 仅支持一个参数,并总是返回 1(...

天地有涯风有信_大海无量不见人
9分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部