J2ME开发优化
1、猜测Vector的长度
2、使用局部变量
3、避免字符串比较
4、将变量和方法声明为final和static,以加快访问
5、使用惰性实例化
6、处理outofmemoryError错误
7、使用数组而不是对象
8、倒计至零的迭代循环,因为和零比较将会较快
9、把引用设置为NULL
10、最大限度的减少方法调用的次数
11、使用移位运算取代乘以二的运算
12、避免类型转换
13、只要有可能、尽量使用Int
14、避免使用异常
相对于J2SE和J2EE开发,很多反常规的方法倒是更加适合J2ME开发
部分内容摘自《More Java Pitfalls 中文版》
J2me程序由于其特殊的运行环境限制,所以优化就显得比较重要,以下是我在学习j2me编程所收集的一些技巧和自己的心得。
本文主要是说明j2me平台上的特殊优化方法,与j2se重复的一些技巧就不再赘述了。
1.显示图象时确定好你的fps,最好先做几次小实验,这样能让你在显示效果和运行速度上有比较好的平衡。
2.GamaCanvas.getGraphics()每次都会产生一个全新的对象,但是对这些对象的操作都是对同一个graphics,所以还是只取一次供后面使用。
3.让多个对象使用同样的监听器,比如让主MIDlet类实现CommandListener和ItemStateListener接口。
4.考虑使用手机开发商提供的一些sdk,没人会比他们更了解他们手机,所以有些时候能显著提高速度,特别是图片,视频使用方面。
5.使用监视工具分析MIDlet的瓶颈,wtk和各个公司提供的开发包里都会有,可以找到程序的弱点。如果是在手机上,用timer测试你认为有可以的地方。
6.使用System.gc(),在无线程阻塞的情况下可以有效的缓解内存压力,但是有些公司不是太推荐使用(如nokia).sun的说法也是越低端的机子执行的越慢,总之,慎用吧。
7.用固定的数组代替使用Vector。
8.图片的优化。考虑使用设备的规格,可能高分辨率的图片不一定显示的出来。
9.不用的对象赋值为null,为更快的回收
10.用混淆器处理你的类文件,防止反编译,还有一个好的副作用就是它减小>
=============================================================
通过Profiler对各种函数及程序的测试,我总结如下结论:
·仅当你需要的时候才去优化代码!
·仅优化那些最耗时的代码!
·使用Profiler去查找哪里需要优化!
·记住Profiler不代表真机上的优化结果,使用System Timer来在真机上做最后的测试!
·在做低级优化之前,总是要先思考算法是否是最优!
·绘图是很占用时间的,所以尽可能的减少Graphics函数的调用!
·尽可能的使用SetClip()来减少绘图区域,相对于SetClip(),drawImage()所花的时间会更可观!
·尽可能的将变量定义在循环以外!
·尽最大可能的进行对需要的数据进行预先计算并将结果保存在缓冲里!
·String类很容易产生垃圾内存,尽可能的使用StringBuffer代替String或用final static来定义之!
·假设是不被接受的,一切要以真机为据!
·尽量使用static final修饰函数,而避免synchronized修饰符!
·对于频繁调用的函数要使用尽可能少的参数!
·尽可能的不使用函数调用!
·尽可能的使用<<和>>来代替*和/!
·使用位操作来代替%运算!
·与0比较比与其他数值比较快!
·数组存取比C语言慢,尽可能不在循环中存取数组!
·局部变量比其他类型的变量运算要快!
·在switch()中尽量使用连续的小数值判断!
·尽量使用乘法而不使用除法!
·尽量使用已有算法!
=========================================================
一般就着手于代码的优化,像电力就没办法了,
J2ME的编程,由于平台的原因,不能像电脑的编程一样,采用很良好的设计,要知道增加代码的数量就可能造成一定
的影响,所以不能完全追求设计而编写,比如setter,getter方法如果不涉及自定义操作的话,可以将变量设成public的,这样一来就可以避免方法调用所产生的开销
还有,图片使用方面,能使用拼图就尽量使用拼图,不要用一张过大的图片,图片的质量能压缩尽量压缩,颜色能少用
就尽量少用.
声音也是一样,尽量用短小的声音,不要使用太大的声音.
尽量少用对象,不用的对象及时NULL掉,图片,声音资源也一样,用的时候加载,不用的时候NULL掉,可以在适当的时候,用Runtime.getRuntime().gc()清下内存,画图的时候用rapint(0,0,屏幕宽,屏幕高),防止超出屏幕外的部分也绘制,尽量用MIDP1.0的方法,效率比2.0的要高,import的时候,只import要用的类,不用的就不导入,记得打包的时候要混淆下,用单线程,少用VECTOR,尽量用定长的对象数组。
---------------------------------------------------------------------------
[原创]J2me的优化之路
[watermark]J2me的优化之路 很多介绍优化的文章里都提到要尽量减少class数量,但是,这真的是有必要的吗?不错,每增加一个空的class大概要多使用100多字节内存,打包后的体积也会有少许增加。但是这样做的好处是更清晰的代码结构,明确的变量使用。因为众所周知,java里没有c/c++里的struct,union,等数据结构,j2me里只有使用class来代替。 代码的优化,不是用搞乱程序结构来实现的。诚然,那样做的确可以或多或少的减小jar体积,但是代价呢?不清晰的流程,混乱的变量使用……,甚至导致无法二次修改、移植。这样的代码,我宁可不要。 真正的优化,是建立在清晰的结构,明确的流程之上的。合理的使用变量,优化数据结构,优化众多不变的数据成为常量,删除无用的代码诸如:System.out.println等调试时期使用的代码。 对于运行速度的优化,几乎是所有编程语言都通用的。请看如下伪代码: Object m_sprite[]=new Object[5]; int i; for(i=0;i<10;i++) m_sprite[0]=xxxxxx; 在for的10次循环中,m_sprite[0]每次都要访问2次地址。为什么?不要问我,有c/c++开发经验的人都应该知道。 如何优化这个部分?请参考下面的代码: Object m_sprite[]=new Object[5]; Object tmp; int i; tmp=m_sprite[0]; for(i=0;i<10;i++) tmp=xxxxxx; 仅仅增加一个变量,就将运行速度提高的近乎一倍。诸如类似的优化方案还有很多,多是千篇一律,大家可以从网上搜索这里就不重复了。请记住一点,所有的优化方法几乎都是通用的,适用于c/c++的,一样适用于j2me。 另外,建议大家使用TimerTask,而不是Thread,除了TimerTask更精确一些外,还因为如果使用Thread方法,就必须依靠wait或sleep来控制时间,但是这两个方法根本无法保证精确性,几乎每个型号的手机都不一样。 排除手机性能的自身问题外,有一部分速度的影响是在屏幕刷新上。paint是一个异步方法,并不是保证立刻刷新,即使调用serviceRepaints也一样。超过屏幕所能接受的刷新频率将导致图象的混乱和更长的延迟时间。 合理的安排资源文件也很重要,jbuilder ,eclipse都具有指定打包后文件所在路径的功能。另外,缩短资源文件名,将多个资源文件合并为一个文件等方法也可以有效的减小jar尺寸,原理在于zip的压缩算法。 最后的优化,建立在一个名叫ProGuard的混淆工具上。目前最新版本是3.4,这个工具的特点是可以删除,合并没用到的class,方法,变量,取消package限制将所有class放到根路径,从而大大缩小jar的尺寸。另外需要注意的一点是,class的数量,请尽量保持在26个之内。否则,混淆后的变量名不但不会缩短,反而会更长。 j2me的优化之路还很长,我仅仅是摸索到了一点点,更多的东西还需要更长的时间去发掘。以上观点,如有不对之处,欢迎探讨。[/watermark]
J2me优化
TCL 发表于 2006-3-31 13:48:00
对我的游戏编程进行总结的时候,我发现有很多东西,都是可以进行优化的。j2me能给我们的并不一定就是我们想要的,in another word,有的东西并不适合游戏的编程。总结如下:
1)尽量要重复利用对象;
2)不用的对象要赋为null;
3)数组代替vector;
4)尽可能少用class,如果能用过程的方法就用,不能的话再考虑对象;
5)方法的速度比较:同步方法<接口方法<实例方法<final方法<静态方法
6)尽量使用final static方法,当然这个方法的含量要少了,这样可以提高速度。
7)数据成员设成public吧,省得要调用函数去修改!
8)在进行循环的时候,我们要使用++i,不要使用i++,我曾经试过,在大型的循环过程中,时间要快1倍。
9)在进行大的数组初始化的时候,最好使用读取的方法,这样可以省去很多内存。比如256*64的数组,如果我们使用interface的话,要用掉24616的memory,而使用读取的方法要使用13408的内存。
代码优化的技术大致分为两个主要方面:高级优化,从使用的整体算法和结构出发进行的优化;低级优化,集中于孤立的代码片断(通常为方法中的代码)的优化。下面分别讨论两方面的优化:
一,高级优化
1, 感觉到就是真实
对于电影来说,我们通过摄像头看到的都是完美的,而在拍摄现场我们看到的却是木头,泡沫和胶带。所以对于电影来说,感觉到就是真实。
游戏也一样,只需要处理游戏需要的东西。在游戏开发的各个方面这都是实用的。把精力集中在使游戏有趣和完美运行的问题上,始终只做需要做的而丢弃其他的部分。
2, 不要创建对象
减少对象创建的总数量和频率,结果能够大大地提高游戏的性能。还必须小心在不经意的情况下产生String对象。
例如:graphics.drawString( 0,0,”Score:” +score );
这一句代码会在每次被调用的时候产生一个新的String对象,在这里就是每一桢画面显示时都会产生新的String对象。因此最好是只是在分数改变的时候才构造这个String。
3, 绘制屏幕
通常,在对游戏完成大量的优化工作以后,收获的将是一个大量时间耗费在屏幕绘图上的游戏。这是因为一个游戏的主要时耗大都集中在绘制图像的工作上(或其他的一些基本的绘图调用)。因此,如果一开始就可以避免绘制工作,那将是对游戏的很好的优化。
还有就是要减少屏幕绘制,循环检测屏幕图像是否在某个部分发生了改变,如果没有,就不要对那部分的屏幕进行更新。另一个方法就是增加绘制图像的尺寸来减少单独的绘制调用的次数。
4, 算法
最好的,也是使用最多的高级优化是对游戏的算法方面。
二,低级优化
1, 提前绘制复杂图像
我们已经知道,使用LCDUI绘制图像是很慢的,因此最好是能够避免这种绘制。其中的一个方法就是用一个预生成图像来减少复杂图像的绘制。进一步来讲,举例:将所有的游戏状态信息整合到一个面板中(得分,生命数,能量值等),然后对这些信息进行一次性同时更新。
2, 保持类和内存之间的平衡
产生新的类会增加JAR包文件的大小,因此应该尽量避免。有的时候增加了额外类的开销可能节省了额外的内存开销,这也是值得的。
3, 复杂值的预计算
节省运算的一个好方法就是对数值进行预运算,从而无需再调用大开销的计算方法。一个很好的例子就是:主窗口画布的高度和宽度就是很好的 缓存对象。例如:可以调用getHeight方法和getWidth方法一次,然后将它们的结果缓存起来,而不是在每一次绘图中都调用这两种方法。
4, 使用数组
在任何时候,只要可能,都应该使用数组而不是Vector,因为数组的运行速度更快。通常面临的唯一问题是,如果最初分配的数组空间不够大,将需要对数组的大小进行扩充。这可以做到,但它需要对整个数组进行重建。例如:
Public final static int[ ] eXPandArray(int [] oldArray, int expandBy)
{
int [ ] newArray = new int [oldArray.length + expandBy];
System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
Return newArray;
}
任何时候,都应该尽量使用一维数组。访问二维数组变量的速度只有访问一维数组变量的一半。当然,仍然可以访问二维数组的对象,只是需要加入一点点计算。例如,与其使用这条语句:
world[y][x] = 0;
不如下面这条语句运行的快:
world[y*tilesWide + x] = 0;
这条语句通过行列的位置将数值转换成一维值,实现了对数组同一元素的访问。
5, 不要使用数组
呵呵,尽管数组的访问比Vector快,但仍然比直接访问变量要慢,因此如果可能就应该删除对数组的访问,或者为一些常用方法中的数组寻求其他能提高性能的办法。
6, 使用快速方法
并不是所有Java调用的方法在性能上都是相同的,方法声明方式的不同对性能会会产生很多的影响。可以使用的最快的方法类型是静态方法,因此应该尽可能多地将代码置于静态调用方法中。运行速度仅次于静态方法的是声明为final的方法。运行最慢的两种方法是在接口中定义的方法和用关键字synchronized声明的方法,必须尽可能地避免使用这些类型的方法。
7, 其他优化
1)异常处理非常缓慢,不要为一半的游戏逻辑使用异常,只用它们来报告真正的错误状态。
2)使用switch表达式比使用if条件语句块的速度要快。
3)尽可能避免使用String对象进行运算,使用StringBuffer。
4)内嵌类的运行很慢,尽可能避免使用。
5)在完成一个引用的使用后将它设为null。
6)不要浪费时间来将一个对象初始化为null或0,java虚拟机会替我们完成这样的初始化
7)多思考新方法,这会使我们的大脑运转的更快。
8)如果可能,尽量使用static,它们运行都很快。它同时适用于方法和域,这条规则就是,如果它可以是静态的,那么就把它声明为静态的。
9)避免类型转换。