您当前的位置:首页 > 好词好句 > 正文

关于J2me性能优化避免内存溢出小结的认识与理解

关于J2me性能优化避免内存溢出小结的认识与理解

J2me性能优化,避免内存溢出总结写程序之初,因为是面向midp2.0的手机而不是游戏开发,所以没有过多考虑性能,大胆使用了很多向量数组(好用:)等。而且程序是随意写的,在手机上开发j2me好像也不是什么事。结果出乎我的意料,我没有办法,只能重新优化。这期间可想而知,浪费了大量时间,开发效率降到了最低。说到这里,只有一句话劝大家,不管你在开发什么样的手机程序,一定要把性能放在第一位,不要重蹈我的覆辙。

我的vectors存储了链接、文本框、图片和普通文本的内容,以及每个vector包含的其他信息,还有它占据的行数、位置和它的logo。我用thread来控制paint(只要目的是实现连续按键的机制),这样每次重绘的时候都要重绘屏幕上的一切和当前的焦点。在重绘的过程中,遍历几乎所有的矢量,每次重绘都是浪费资源的。结果是一样的,在稍微低端一点的手机上反应明显慢。要优化这样一个程序,我首先想到的是用其他方法代替vector。正常的表现是用字符串->一维数组->二维数组->向量。一维数组代替不了我的向量,只好用二维数组。费了好大劲才把vector转换成二维数组,发现性能提升不大。大概只省了20k左右的内存,只能想别的办法了。以下是获取手机当前内存和剩余内存的简单方法:

longtempMin=1000000

longtemp=Runtime.getRuntime()。freeMemory();

if(tempMin"temp){

tempMin=temp

}

g . drawstring(total=runtime . get runtime()。totalMemory(),10,10,0);

g.drawString(frees=temp,10,10 lineHeight,0);

g.drawString(hiegh=tempMin,10,10 2*lineHeight,0);

把这些东西画在画布上,这样就可以检查在真实机器上运行时的内存使用情况。每台机器的最大内存都不一样。

你可以看到记忆峰值。当然也可以用wtk自带的内存和方法查看器来判断。

既然转换向量解决不了问题,那就继续优化吧。内存的主要使用好像是在每次重绘的时候产生的,这样每次重绘的内容都会减少。我采取的方式是把固定要重画的东西都用双缓冲的方式画在一张图片上,这样我在初始化的时候只遍历数组,一次遍历完就把所有内容画在一张图片上,然后每次重画一张图片。经过这种处理,性能有了很大的提高。现在高兴还为时过早。诺基亚的低端机没有问题。结果它在moto的机器上出了问题,根本无法初始化,也就是说创建图片的时候应用出错了。继续找原因,结果发现moto的机器不支持创建那么大的图片。也就是说,你在创建大图的时候,在moto的机器上根本无法申请内存。找到原因后,把大图分成两个小图,ok就没问题了。当然,至于moto支持创建多大的图片,可能每台机器都不一样,需要的时候只能自己测试了。对于浏览器来说,将一个页面分成两个页面需要一些代码处理。其实为了优化性能,一个大图可以分成若干个小图,每个小图的大小可以按照屏幕大小的几倍来确定,也可以根据型号来固定。初始化的时候,也可以先初始化一些图形。因人而异。

至此,程序的主要瓶颈已经找到并解决。作为响应,程序花80%的时间执行20%的代码。也就是说要重点优化那20%的代码,但其实我发现另外80%的代码优化也很重要,主要是处理一些编程细节。更加注重代码的详细编写也有利于程序性能的提高。关于细节,我认为以下几个方面对提高节目的表现很有帮助。

首先是系统垃圾回收的利用:至于堆内存和栈内存,我们知道堆存储的是对象实例和变量;堆栈存储静态方法。堆内存是在JVM启动时创建的,存储在堆内存中的对象可以被JVM自动回收。这里,您应该手动将未使用的对象设置为null,尤其是大型对象。如果你不用它们,你一定要记得留空白。例如,大数组、向量或图像对象。(不要)这里我是在后台读取浏览器中的页面图片,也就是先显示文本部分,然后在后台读取页面中的图片,读取后再一起显示。再放的时候要重建双缓冲图片,但是当时忘了把原来的双缓冲图片设置为null,走了很多弯路才解决问题。所以至少不要清空大型对象,也不要指望垃圾回收。

其次是静态的使用:静态变量的内存空间在程序运行过程中是为这个类的所有对象实例所共享的,也就是在内存中只保留一个副本,节省了不必要的内存开销。但static生命周期长,不易被垃圾收集机制回收,应合理使用,不可适得其反。建议在以下所有情况下尽可能使用静态变量:

1),变量包含的对象大,占用内存多。

2)、变量所包含的对象的生命周期长。

3)、变量中包含的对象数据是稳定的。

4),这个类的对象实例有共享这个变量包含的对象的要求。

我的程序在静态变量优化之后,程序占用的内存量至少增加了5 K-10 K .所以不能忽略。

还有跟字符串类相关的东西:1。累积字符串时,必须使用StringBuffer的append方法,不要使用运算符连接两个字符串。差别很大。而且不要在循环或者一些重复的动作中创建一个String对象,因为一个String对象是要用StringBuffer对象来处理的,一个String对象要产生三个对象(大概是这样:)。

2.使用string length()方法获取字符串长度时,不要把长度放在循环中,可以在循环外取值。(包括向量的大小法)。尤其是循环多的时候,尽量把长度放在循环之外。

intsize=XML vector . size();

for(inti=2;我。

}

我曾经在程序里误写了这样一句话:if(i=5){。},编译器没有报错,结果好像是I的值变了,也不清楚。有兴趣的话可以测试一下。写的时候尽量认真,不然找bug的时候可能会心烦。

优化代码最简单的方法就是首先不要调用它。这并不是说你要删除这些代码,也许你可以用其他方式调用它们(后者实际上减少了对它的调用)。游戏的主循环是游戏运行最重要的,要更多的考虑是否可以避免或者减少属于这个区域的代码。在上一篇文章中,我们介绍了内存评估工具的方法和使用,但它们只能帮助我们找出哪些代码降低了程序的运行速度。以下内容是参考其他资料优化代码的方法。

代码优化的技术大致可以分为两个主要方面:高级优化,基于使用的整体算法和结构的优化;低级优化侧重于隔离的代码片段(通常是方法中的代码)的优化。下面讨论优化的两个方面:

一、高级优化1、感觉是真实的

对于电影来说,我们通过镜头看到的是完美的,但我们在拍摄现场看到的是木头、泡沫和胶带。所以对于电影来说,感觉是真实的。

游戏也是一样,只需要处理游戏需要的东西。这在游戏开发的各个方面都很实用。专注于让游戏变得有趣和完美的问题,永远做需要做的事情,抛弃其余的。

2.不要创建对象。

减少创建对象的总数和频率可以大大提高游戏的性能。您还必须小心不小心生成的字符串对象。

例如:graphics.drawstring (0,0,“分数:”分数);

这段代码每次被调用时都会生成一个新的String对象。在这里,每次显示一个帧时,它都会生成一个新的String对象。因此,最好只在分数变化时构造这个字符串。

3、绘制屏幕

通常在为游戏完成大量的优化工作后,收获的会是一款花费大量时间在画面绘制上的游戏。这是因为一个游戏的主要时间消耗大多集中在画图(或者其他基本的画图调用)上。所以如果能从一开始就避免画图工作,会是一个很好的游戏优化。

还有就是要减少屏幕绘制,定期检查屏幕图像某一部分是否有变化。如果没有,就不要更新屏幕的这一部分。另一种方法是增加绘图图像的大小,以减少单独绘图调用的次数。

4、算法

最好和最常用的高级优化是游戏的算法方面。

二、底层优化1、提前绘制复杂图像

我们已经知道用LCDUI绘制图像非常慢,所以最好避免这种绘制。方法之一是使用预先生成的图像来减少复杂图像的绘制。进一步的,比如把所有的游戏状态信息整合到一个面板里(分数,生命,能量值等。),然后一次性更新这些信息。

2、保持课堂和记忆的平衡

生成新类会增加JAR包文件的大小,所以应该尽可能避免。有时增加额外的类开销可能会节省额外的内存开销,这也是值得的。

3、复数值的预计算

节省计算的好方法是预先计算好数值,这样就不需要调用昂贵的计算方法。一个很好的例子是:主窗口画布的高度和宽度是很好的缓存对象。例如,您可以调用getHeight方法和getWidth方法一次,然后缓存它们的结果,而不是每次绘图都调用它们。

4.使用数组

只要有可能,应该使用数组而不是Vector,因为数组运行得更快。通常面临的唯一问题是,如果初始分配的数组空间不够大,则需要扩展数组的大小。这是可以做到的,但是需要重建整个阵列。例如:

public final static int[]expandArray(int[]old array,int expandBy)

{

int[]new array=new int[old array . length expandBy];

System.arraycopy(oldArray,0,newArray,0,old array . length);

返回newArray

}

在任何时候,你都应该尝试使用一维数组。访问二维数组变量的速度只有访问一维数组变量的一半。当然,仍然可以访问二维数组中的对象,只是需要增加一点计算。例如,不使用此语句:

world[y][x]=0;

不如下面的语句快:

world[y * tiles wide x]=0;

该语句通过行和列的位置将数值转换为一维值,实现对数组的同一个元素的访问。

5.不要使用数组。

虽然对数组的访问比Vector快,但还是比直接访问变量慢,所以如果可能的话,应该删除对数组的访问,或者在一些常用的方法中寻找其他方法来提高数组的性能。

6.使用快速方法

Java调用的方法并不是性能都一样的,方法声明方式的不同会对性能产生很多影响。可以使用的最快的方法类型是静态方法,所以您应该将尽可能多的代码放在静态调用方法中。除了静态方法,声明为final的方法运行得更快。两个最慢的方法是在接口中定义的方法和用关键字synchronized声明的方法,必须尽可能避免这类方法。

7、其他优化

1)异常处理非常慢。不要对一半的游戏逻辑使用异常,只用它们来报告真实的错误状态。

2)使用switch表达式比使用if条件语句块更快。

3)尽量避免使用String对象进行操作,使用StringBuffer。

4)嵌入式类运行速度慢,尽量避免使用。

5)在引用被使用后将其设置为null。

6)不要浪费时间将对象初始化为空或0。java虚拟机将为我们完成这个初始化。

7)多想想新的方法,会让我们的大脑跑得更快。

8)如果可能的话,尽量用静态。他们都跑得很快。它适用于方法和域,规则是如果它可以是静态的,就声明它是静态的。

9)避免类型转换。

10)在优化方案的时候,要做出选择,更要有预见性。有什么好的建议吗?让我们一起成长。

一起讨论:zxhwolfe@hotmail.com

附件:j2me程序调试

用eclipseME WTK2.1调试J2ME应用——引用mingjava的帖子。

选择Windows-首选项-Java-调试。不要选择暂停执行的前两个选项。将调试程序超时选项中的第一次设置为至少15000毫秒,以便可以进行调试。

《script src=“http://partner.googleadservices.com/gampad/google_service.js” type=“text/javascript”》 《/script》 《script type=“text/javascript”》 《!-- try { GS_googleAddAdSenseService(“ca-pub-4210569241504288”); GS_googleEnableAllServices(); } catch (e) { } // --》 《/script》 《script src=“http://partner.googleadservices.com/gampad/google_ads.js”》 《/script》 《script type=“text/javascript”》 《!-- try { GA_googleAddSlot(“ca-pub-4210569241504288”, “cnblogs_commentbox_up”); GA_googleAddSlot(“ca-pub-4210569241504288”, “cnblogs_blogpost_bottom”); } catch (e) { } // --》 《/script》 《script type=“text/javascript”》 《!-- try { GA_googleFetchAds(); } catch (e) { } // --》 《/script》


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 三思而后行的意思指哪三思(三思而后行的意思)

下一篇: 苹果appstroe(苹果手机appstore无法登录)



推荐阅读