Midlet size

I wanted to start a thread about how to minimize size of midlets. At work we’ve hit the 64KB limit of OTA, and MIDP 1.1 specification. We knew we were going to hit it, and so we made a lot of “optimizations” to ensure we won’t have any size issues.
Most of the work thus far (bar some image optimization techniques) has been “uglyfication”, by which I mean: inline stuff, increase visibility of fields and so forth. Though we are well below the 64 KB limit again (wohoo) I would like to make it even smaller.

How did you you guys solve these issues? - What optimizations saved you most bytes?

It should be said, that content needs to be packaged in the midlet suite, and that the midlet is already being obfuscated.

I reduced the number of classes I used. First by mergeing as many classes as possible. Then by using arrays instead of smaller classes like bullets.

This is of course as ugly as it gets, but might save a couple of k. Only do it if you are desperate :wink:

yeah, that was also part of our “uglyfication” :wink:

One of the biggest gains, was by grouping images together, and then having an array that contained regions on the main picture to paint from. This saved us a lot of Image refernces, but most importantly we shaved several PNG headers of the image files.

It’s funny that doing j2me is actually somewhat counter java intuitive, in that one has to limit classes and abstraction to almost non existant, sort of like coding to the metal in the good old days :slight_smile:

another simple byte shaver (though it will hit performance) is to use if/else instead of switch statements.
The problem with switch is hat it builds a lookup table, which wastes much more bytes than an if/else construct. Ofcourse this is also slower.

I’ve seen anything from 10-300 bytes savings on doing this - ofcourse dependent on the size of the switch statement.

btw, one thing that really annoys me, is that we have to use a zip compresion for jar files. If the RAR format (though it won’t be, since it is proprietary) was supported we’d have 1/3 better compression!

I particularly like the way that the Pre-verifier adds (at least for me) 15%-22% size increase to the class files!!

Have a go at compiling your classes manually then look at the class file size before and after Preverify and note how much bigger they get…

Does anybody actually know what the Preverifier actually does? Its only supposed to add a stack map attribute to each method but I’ve come across classes it does not seem to touch.

Thats another way to squeeze those class files, use as few methods as possible!

The MIDP V1.0 spec states that for memory consumption the minimum should be:

128K of non-volatile memory for the MIDP components.
8K of non-volatile memory for application-created persistence data
32K of volatile memory for java runtime (heap etc).

All these other limitations (such as max class file size, or jar file size) are just imposed by the manufacturer.

For example almost all (if not all) current (2003) Siemens phones have a wonderful size constraints of 16K on everything:

MIDP V1.0 spec (thats JSR-37) can be found here:
http://jcp.org/aboutJava/communityprocess/final/jsr037/index.html

MIDP V2.0 spec (JSR-118 ) :
http://jcp.org/aboutJava/communityprocess/final/jsr118/index.html

And a list of all the JSR extensions for J2ME can be found here (all 55 of them!):
http://jcp.org/en/jsr/tech?listBy=1&listByType=platform

Whats needed is a list of phones (or KVM’s) and their limitations. Because manufacturer are quite happy to leave out this information from specs.

I had hoped www.jbenchmark.com would, but they don’t even seem to bother filtering out bogus scores.


Woz.

  • reduce the number of classes, never use inner class

  • remove all unecessary String or “something” object

  • remove number of variables

  • use simple type instead of object

  • reduce number of image files, combine multiple images into one

  • reduce the use of try-catch block

  • try not to cross reference other classes

  • and of cause, obfuscator

  • sometimes, restructure your code will work, too!

hope this help
ben

it adds stack map only to those class that use branch bytecode operation. if you use try-catch, if-then-else and switch-case, your classes will add a lot of size because of the stack map. avoid those.

(note: i am not 100% sure which statement translate to branch operation, correct me if i am wrong. it is just my observation)

ben

no1 has mentioned the 2nd biggest saving (after obfuscation)

Use a proprietary image format specific to the device you intend to deploy on,
Compression isn’t necessary, the jar will compress it pretty well anyhow (though having a simple RLE algorithm may save u a little bit more)

Then, pack them into a single file, images.dat or something. (less files in a jar, the smaller the jars index table)

To read the images in, you will need to use manufacturer specific calls, but both the Siemens and Nokia extensions provide the necessary methods.

Doing this will both accelerate load times, and decrease app. size.

Another tip is to use winzip or somthing similar, instead of the jar utility. jar do not do a good job of compressing.

indeed, from what I remember 7zip gave the best compression ratio.

if you use other zip utility, will the phone still be able to uncompress the jar file correctly?

just wonder…

ben

Currently, we use WinRar to shave off ~1 kB, and this works fine. As long as it’s the std zip compression rutine you’re fine. I’ll have a look at 7zip…

Hmmyea… yummy uglyfication ;D


//air friction :>
//if(xVel>LR_FRICTION)
//      xVel-=LR_FRICTION;
//else if(xVel<-LR_FRICTION)
//      xVel+=LR_FRICTION;
//else
//      xVel=0;
//OPT: 24 bytes saved. "()" for readability, doesnt change anything.
xVel=xVel>LR_FRICTION?xVel-LR_FRICTION:(xVel<-LR_FRICTION?xVel+LR_FRICTION:0);

One class is enough… if you still can squeeze out some bytes without using too much performance your code isn’t ugly enough yet.

Well yea… once you’re done it looks like messy bad-style C code.

Oh and it might be worth a try to run over it with 2 different obfuscators :slight_smile:

Hmm, 7zip did indeed compress it even better - thanks!

Hello Woz,

can you tell me which results are bogus on www.jbenchmark.com?

Thank you for your help
Laszlo Kishonti
JBenchmark developer

Hi Laszlo,

Those scores for the T-610 look extreme fishy, they are all over the place. A genuine score seems to be ~279, yet there are scores up to 402 and as low as 175. But the dates are intermixed, so a recent score does not mean a higher score (so would not suggest a firmware update).

http://www.jbenchmark.com/index.html?F=D&D=SonyEricsson%20T610%20T616

This seems a bit funny for a device which has not been changed (as in a faster CPU for new versions) or (to my knowledge) a faster KVM + libraries.

The T-610 is not a fast beast when it comes to J2ME, it used to be 3rd from bottom on your list at one point. Which is rather disappointing as the phone is quite good.

Of course it could be just down to the benchmark being interrupted, or even an inaccurate system clock.

A system clock accuracy test would be a good one to add to JBenchmark, at least it would be informative (would also force phone Manufacturers to at least try and make them accurate, because it would look bad if they didn’t).

You also don’t impose a penalty for failing a test, the T-610 cannot generate an image larger than its screen size and so fails the animation test.

Got to ask, whilst I’m at it, whats ATi’s connection with your JBenchmark 2 are they about to launch a mobile gfx chip? Your NDA is safe with us, we can keep a secret! Honest :smiley:

All the best with JBenchmark2,

Woz.