Jump to content

  • Log In with Google      Sign In   
  • Create Account

Anyone have some hardcore J2ME optimisation tips?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
38 replies to this topic

#1 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 22 March 2005 - 05:54 AM

I need some hardcore optimisation tips for J2ME. Anything at all please, apart from inlining and not using objects. I mean good tips now, unobvious ones. I will greatly appreciate any help.

Sponsor:

#2 Zahlman   Moderators   -  Reputation: 1666

Like
0Likes
Like

Posted 22 March 2005 - 10:54 AM

Remember that arrays are objects; try to reduce their number, and avoid multiple-dimensional ones (you don't need the flexibility anyway; java arrays are basically a non-resizable std::vector, they have all the other stuff).

Beyond that, I'd have to see some code...

#3 widggman   Members   -  Reputation: 100

Like
0Likes
Like

Posted 22 March 2005 - 11:06 AM

If it's like J2SE, do not use string concatenation like this:
String a = "";
for (...)
a += "some string" + "other one";

use a StringBuffer:
StringBuffer a = new StringBuffer("");
for (...)
a.append("some string").append("other one");

because the compiler transforme any string manipulation like:
a = b + c;

in this:
a = new StringBuffer(b).append©.toString();

It a lot of useless creation of new object
an you can reset de contain of a StringBuffer... it's probably faster than
create a new one...

P.S. excuse my english

#4 Miranda   Members   -  Reputation: 514

Like
0Likes
Like

Posted 22 March 2005 - 11:10 AM

Make good use of the method profiler that comes with Sun's J2ME wireless toolkit. It will let you know where the the majority of your processing time is. It's an excellent tool.

#5 Sneftel   Senior Moderators   -  Reputation: 1744

Like
0Likes
Like

Posted 22 March 2005 - 11:21 AM

The number one thing you should do is improve your algorithms. Tricks like making methods static, not including inner classes, etc. are useful for getting the last 10% out of a MIDlet, but if you can improve the flow of your program to reduce computation, the gains can be an order of magnitude larger. As Miranda said, the profiler is very useful for figuring out where you're spending all your time.

#6 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 22 March 2005 - 08:34 PM

Thanks for that StringBuffer one, although I don't use any Strings in the main loop. Someone told me making methods static does not always give you the speed gains you need. Also with the profiler, if you have most of the code inline anyway how can you tell which area is causing most hang ups?

Zahlman: how can i get away without using arrays in a simulation where I need vector mathematics? I know i oculd define an int x,y for every vector, but that just gets messy.





#7 Frank Henry   Members   -  Reputation: 186

Like
0Likes
Like

Posted 23 March 2005 - 12:43 AM

These should get you on the right track:

http://www.javaperformancetuning.com/tips/j2me.shtml

http://www.developer.com/java/j2me/print.php/10934_2234631_1

http://www.protomatter.com/nate/java-optimization/

http://www-2.cs.cmu.edu/~jch/

http://www.javaworld.com/jw-04-1997/jw-04-optimize.html

http://www.javaworld.com/javaworld/jw-09-1998/jw-09-speed.html


#8 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 23 March 2005 - 02:00 AM

Thanks again I found some interestings sites in my own research. Most of it is C code but can adpapt really well to mobiles and I'm sure console programmers will appreciate. My J2ME game is a pool sim so the stuff below has been extremely useful. The below are very "hardcore" optimisation tricks. Here are the sites for everyone else's benefit:

http://www.cs.uiowa.edu/~jones/bcd/divide.html

http://aggregate.org/MAGIC/

http://www.dspguru.com/comp.dsp/tricks/index.htm

http://www.azillionmonkeys.com/qed/tech.shtml

http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf

http://www.worldserver.com/turk/computergraphics/InverseSqrt.pdf


#9 doynax   Members   -  Reputation: 850

Like
0Likes
Like

Posted 23 March 2005 - 02:07 AM

How about writing raw byte-code?
Would it be a viable option for size/speed optimizations, and is the virtual machine complex enough to be outperformed by a decent assembly programmer?

#10 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 23 March 2005 - 08:41 AM

Yeah I'm not ready to learn raw byte code yet!

#11 Frank Henry   Members   -  Reputation: 186

Like
0Likes
Like

Posted 23 March 2005 - 09:47 PM

Thing is hardcore optimizations are nice but if you find you really need them development on a mobile might not be the ideal place for your project.

Some mobiles are horribly slow.
There was a topic like this here allready, seach for it.
(Zahl and I posted in it as well)

Here are some quick suggestions:
replace for with while loops.

reference fields in local functions.
i.e.
instead of this.m_bigassarray
do int[] bigassarray = this.m_bigassarray

Not only with arrays but with everything.
Every access directly to arrays or classes costs you time.

Also every array dimension you need to access costs ya.

Use ints! The others take less space but using them is more expensive.

Do not create Objects at runtime.
No, avoid them like the pleague!!
You can usually get by with int arrays.
If you REALLY REALLY need them, recycle them!
Create the amound you presume you will need ahead of time and hold them in a sepperate vector, when you want to create one, fetch it out of the backup vector and use it. When you are done put it back in.

o.c. you have the standard optimizations:
save on not needed/redundant calculations
shifting better then division/multiplications

#12 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 23 March 2005 - 10:42 PM

Quote:
Original post by Frank Henry
Some mobiles are horribly slow.


Tell me about it, but I've no choice. I've got 6-18fps on a 3200 , I'm impressed as it is a slow phone. I need to get average 15fps you see, cause according to the mobile developer grapevine thats what gameloft's development team on Midnight Pool has got, as this is a competing game. I have to get this running acceptably on all S40's as well [bawling]. I haven't seen another Pool game running on S40 at accetable rate, in J2ME at least.

Quote:
Original post by Frank Henry
replace for with while loops.


done.

Quote:
Original post by Frank Henry
reference fields in local functions.
i.e.
instead of this.m_bigassarray
do int[] bigassarray = this.m_bigassarray


Most of the varibles are local already, and I'm not using any classes.

Quote:
Original post by Frank Henry
Also every array dimension you need to access costs ya.


Arghh!!! How much cost? I really don't want to slpit it into 1D arrays, but if I have to I will. Will splitting it into 1D arrays help as I still have to reference 2 int arrays every loop?



#13 Zahlman   Moderators   -  Reputation: 1666

Like
0Likes
Like

Posted 24 March 2005 - 11:25 AM

Quote:
Original post by pkelly83
Quote:
Original post by Frank Henry
Also every array dimension you need to access costs ya.


Arghh!!! How much cost? I really don't want to slpit it into 1D arrays, but if I have to I will. Will splitting it into 1D arrays help as I still have to reference 2 int arrays every loop?


If your array is rectangular, don't split it - join it. And calculate the indices manually. (Possibly this may involve caching index values and adding some offsets...) int[][] is overly flexible; it doesn't enforce rectangularity, so if you don't need that freedom, you're paying unneeded overhead.

#14 markr   Members   -  Reputation: 1277

Like
0Likes
Like

Posted 24 March 2005 - 12:00 PM

Unfortunately on many devices there are no profilers, so the standard response "use a profiler" is not very helpful.

What you would be profiling would be the desktop J2ME implementation which is likely to be running a totally different JVM and libraries from the actualy phone.

Many "Emulators" (I use the word looseley here) actually don't emulate the device at all, rather they just simulate the vendor-specific libraries - and do so in a fashion which bears absolutely no resemblance, performance-wise, to the device itself.

I've no idea how accurate the timers are on these devices so you can try to roll your own on-device profiling, but I suspect not very accurate.

Anyway I pretty much suss it out by observing the behaviour of the game with different numbers of different objects on the screen.

I've found that the graphics library is so incredibly slow, that even if my code were horribly inefficient, it would still make little difference.

Of course this depends what sort of game it is, you might have to do some intense stuff.

But in any case, you should focus on better algorithms, not micro-optimising code which you're not sure whether it's important because you can't profile it correctly.

Mark

#15 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 24 March 2005 - 11:08 PM

Quote:
Original post by markr
I've found that the graphics library is so incredibly slow, that even if my code were horribly inefficient, it would still make little difference.


Yep thats the main problem right now acoording to both WTK's profiler and timing on the phone itself. 50% of my frame time is taken by graphics drawing.


#16 Zahlman   Moderators   -  Reputation: 1666

Like
0Likes
Like

Posted 25 March 2005 - 10:18 AM

Make use of buffering techniques to avoid redrawing things on screen which haven't changed since the last draw. Typically, you allocate a screen-sized (or slightly larger, depending on application) offscreen buffer, and do your drawing to that; on each game "tick" you just blit the buffer to screen. Then you require additional state information to describe "what is currently drawn on the buffer", so that you can minimize the amount of drawing you do on that buffer (by not drawing things that are already there, basically).

Also, compare the drawing speeds of various primitives and images (for images, compare clipped and non-clipped), and make use of this information.

#17 pinacolada   Members   -  Reputation: 834

Like
0Likes
Like

Posted 25 March 2005 - 11:43 AM

Hey I'll second that note about optimizing the drawing. I worked at a cell phone game place for a while, and churned out quite a few games for them. Whenever a game needed to be optimized, the first (and often only) thing I ever optimized was the drawing. Drawing to the screen is a huge, enormous bottleneck on phones. And the non-drawing code generally runs pretty fast. I rarely found it worth my time to optimize the "algorithmic" code (the code not related to drawing). I'd say, unless you have an algorithm that iterates more than 10k times, don't bother optimizing it.

There are two main ways to speed up drawing:

The first is "dirty-recting". You keep track of which screen elements are "dirty" (in need of redrawing), and you only redraw those elements. This one only works if there is a lot of stuff that stays still. It doesn't really work if the whole screen changes every frame, like say Super Mario Bros or something.

There are different ways to do dirty-recting. My favorite method is to keep track of the dirtyness in terms of rectangles. Every time something happens that makes something on the screen dirty (like say, the score changes, or the main character steps on a landmine and begins an explosion animation), you calculate the rectangle that encompasses this element, and you add it to a dirty rectangle list.

Then, when you redraw the screen, you first go through your dirty rectangles and "coalesce" them. That is, you check each rectangle against the others to see if it overlaps a lot, and if they overlap, you combine the two into one big rectangle. The strategy I actually used was that if two rectangles intersected *at all*, I would combine them. And in some games, it worked well to just always combine every rectangle into one big one. The needs of your game may vary.

Once you have your list of remaining rectangles, you loop through each rectangle, set the cliprect to that rectangle, and then call your draw function as normal. See, the nice thing about this method is that you don't have to change your draw function at all, the optimization comes from using cliprects. The theory here is that when the drawing code results in a draw call to a part of the screen that's clipped out, that code will be executed in a trivial amount of time.

Personally I don't really trust a Java Image to actually do nothing when I try to draw it somewhere where it is completely clipped out, so I recommend having your own Image wrapper class (if you don't already), which, when you draw it, checks itself against the current cliprect and returns immediately if it is clipped out.

You might balk at adding all that extra processing, and be worried that all that extra work will slow you down. But trust me, that processing is totally worth it if you can reduce the amount of drawing you do. Draw calls are an enormous, huge, un-small time sink.

The other good way to speed up drawing is to cache things onto an offscreen buffer. I almost never used this method for the games I worked on, because we pretty much always had the phone's runtime memory completely stuffed with art assets, and we couldn't spare the extra memory. This might not be a problem for your game.

#18 PurpleAmethyst   Members   -  Reputation: 285

Like
0Likes
Like

Posted 25 March 2005 - 11:40 PM

Quote:
Original post by pinacolada
The first is "dirty-recting".


That is a good idea, I even used this before on home made PC games I wrote. I just never really thought about using it on the phone. Guess I can use that joined arrays trick to store the rectangles in a 1D array. Thanks for that idea, that is thinking outside the box. You could even compress it into one int using right shifts as the screen is only 128x128 on an S40, and that will work on S60 too. Sweet.

Quote:
Original post by pinacolada
This might not be a problem for your game.


Believe me, memory is a big problem. We are using a buffer already and it's still slow.

#19 Woody FX   Members   -  Reputation: 169

Like
0Likes
Like

Posted 26 March 2005 - 06:58 AM

So what you are saying is to draw everything to an offscreen image (buffer).

Then draw this complete image to the screen in one draw to the 'actual' screen.

Is it faster drawing to the (buffer)image say 10 times and then only drawing 1 large image to the phones screen?

About dirty-recting is that just setting clip regions so the when the buffer image is drawn to the screen only the smallest amount of pixels on the screen need updating are updated?

So from that i take it thats its the actual drawing the the screen thats slow and not all the 'draw' methods themselves that are slow.


#20 pinacolada   Members   -  Reputation: 834

Like
0Likes
Like

Posted 27 March 2005 - 02:53 AM

Well, they are both slow. Drawing takes time based on both: 1) the sheer area (number of pixels) you are trying to draw, and 2) the number of draw calls you are making. This varies between phones, too. On some phones, the number of draw calls doesn't matter so much, on other phones it matters a lot more.

So having an offscreen buffer is good, because when you draw it to the screen, you have reduced the number of draw operations to just one. But you still don't want to redraw the entire screen if you can help it, because this involves repainting a large amount of area, which will also be slow.

I myself don't know how much faster offscreen buffers are, since I didn't use them much. It might even be possible that drawing to an offscreen buffer isn't faster than drawing to a screen at all.

But one thing that's definitely faster is to "cache" the drawing. Say you have some element that requires several draw calls (like maybe the game background), but doesn't change during the game. You draw this element to an offscreen buffer once, then once you have the completed image in the buffer, you can draw it to the screen and it will only cost you 1 image draw per frame. This method can even work on screen elements that *do* change, but they change infrequently. Every time the screen element changes, you have to take the performance hit of redrawing the offscreen buffer- but you'll still have a performance improvement for most of the time.

So here is the executive summary:

Quote:
Original post by Woody FX
Is it faster drawing to the (buffer)image say 10 times and then only drawing 1 large image to the phones screen?

Don't know

Quote:

About dirty-recting is that just setting clip regions so the when the buffer image is drawn to the screen only the smallest amount of pixels on the screen need updating are updated?

Yes

Quote:

So from that i take it thats its the actual drawing the the screen thats slow and not all the 'draw' methods themselves that are slow.

They are both slow.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS