Home | Table of contents | mBooster User Guide | Optimizations | Properties | FAQ |

This page last changed on Aug 26, 2005.

Optimizations

mBooster performs a wide spectrum of optimizations. It is not possible to list and fully describe every optimization performed by mBooster. Instead this section aims to
  • highlight optimizations that can be switched on and off through property settings
  • highlight optimizations that could significantly benefit from an alteration of programming style
  • highlight the best practices to get the most out of mBooster to reduce development time and effort

Table Of Content: Optimizations




Class And Interface Merging

Property settings

This optimization is turned ON by default.
In the property file,
OPT.CLASS.MERGING=ON turns on this optimization
OPT.CLASS.MERGING=OFF turns off this optimization
 

mBooster reduces the number of classes and interfaces by combining them together. The merging performed will not increase heap memory usage.
To guarantee correctness, the extensive safety checks are by necessity conservative. The user may relax some of these checks through this set of properties.

If a class is specified in the REFLECTEDCLASSES property, it is excluding from merging.
Tips
  • This optimization is particularly useful in conjunction with an objected oriented programming framework. It reduces the overhead of the object oriented programming style.
  • Keep the class initializer and static field initializers simple. A complex class initializer or static field initializers, for example one that calls methods in a different class, is likely to rule the class out from class merging.
 



Method Inlining

Property settings

This optimization is turned ON by default.
In the property file,
OPT.METHOD.INLINING=ON turns on this optimization
OPT.METHOD.INLINING=OFF turns off this optimization
 

The current implementation of method inlining is designed to minimize the resulting JAR size. It can also significantly improve run-time performance.

Some handsets, including handsets embedding Sun's HotSpot J2ME virtual machines, are known to degrade performance on large methods. Different handsets have different method size thresholds. Through this set of properties you can specify the thresholds such that the application performance is not degraded.
Tips
  • It is not recommended to inline methods manually. The different method size limits imposed by different handsets will likely cause performance issues on some handsets.



Array Initialization Optimization

Property settings

This optimization is turned ON by default.
In the property file,
OPT.ARRAY.INIT=ON turns on this optimization
OPT.ARRAY.INIT=OFF turns off this optimization
 

The Java compiler generates space inefficient code for array initialisation. Typically, it takes about 3-6 bytes to populate each element in an array.

class LevelData {
    // Some comments here
    static final int SNOW = 1;
    static final int HILL = 2;
    static final int POND = 3;

    static final int[][] MAP = { 
        {SNOW, SNOW, SNOW, HILL, HILL, HILL },
        {SNOW, POND, POND, SNOW, SNOW, HILL },
        {SNOW, POND, POND, HILL, HILL, HILL },
        ....
        {SNOW, POND, HILL, HILL, POND, HILL },
        {SNOW, SNOW, SNOW, HILL, HILL, HILL }
    };

    int[] intArray1 = {1, 2, 4, -1, 29, 100, 2, 9};
    int[][] enemyPositions;

    // Constructor
    void LevelData() {
        ....
        // Calls initEnemyPosition() to set up initial position of enemies
        initEnemyPositions();
        ....
    }
        
    // Method to set up initial position of enemy
    void initEnemyPositions() {
        enemyPositions = new int[][] { {
            4,3}, {5,4}, {3,1}, {5,2}, {10,1}, {8,3}, {10,0}, {1,1} };
    }

    ...
}
 

mBooster automatically optimizes array initialization that occurs within class initializers and constructors, and methods they call, where it is determined that it will be space efficient. mBooster optimized array initialization is

  • much faster than loading an external data file
  • typically more space efficient than loading an external file
  • has no impact on performance other than class initialization, and instantiation
  • works for multidimensional int, short, byte arrays

In the example above, mBooster will automatically optimize the initialization of MAP, intArray1, and enemyPositions.

Be Careful

Array Initialization Optimization could increase the heap usage of the application. If your application is very tight in heap memory, please consider turning off this optimization.
 
Tips
  • Initialize arrays in Java source code, rather than loading from an external file
  • Keep the value range in an array as small as possible for best optimization
 



Resource Packing

Property settings

This optimization is turned ON by default.
In the property file,
OPT.RESOURCE.PACKING=ON turns on this optimization
OPT.RESOURCE.PACKING=OFF turns off this optimization
 
Resource packing reduces the overall size of a MIDlet's JAR file by automatically packaging the resource files available to the application into a small number of special packed resource files. The packed resource files have greater compressibility, and by reducing the number of files it helps to reduce the overhead in the JAR file. Although resource packing can be done programmatically in Java, mBooster implements very efficient algorithms that would for most circumstances result in significantly smaller overall JAR files. In addition mBooster allows you to vary the key parameters for resource packing without altering any source code. This flexibility is particularly useful when you are building multiple SKUs for different devices.
Warning

You MUST
if the application uses any method within the system library to access the resource files, except through:
  • public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String), defined in CLDC 1.0 API
  • public static javax.microedition.lcdui.Image javax.microedition.lcdui.Image.createImage(java.lang.String), defined in MIDP 1.0 API
  • public com.sprintpcs.media.Clip(String resource, String MIMEType, int priority, int vibration), defined in Sprint API
  • public static javax.microedition.m3g.Object3D[] javax.microedition.m3g.Loader.load(java.lang.String name), defined in JSR-184 API

Resource packing optimization can be configured in a flexible manner through this set of properties.

Resource packing optimization is currently not supported for DoJa applications. This optimization will be automatically turned off when optimizing an DoJa i-appli, i.e. when the property JVM.PLATFORM is set to J2ME_DOJA.

When using the JSR-184 API and the Loader from public static javax.microedition.m3g.Object3D[] javax.microedition.m3g.Loader.load(java.lang.String name), the ability for the JSR-184 file format (.m3g) to hold external references must be considered. If a file loaded through the Loader.load() function contains an external reference to another file from the application JAR, then the externally referenced file must be excluded from resource packing through setting the RESOURCE.PACKING.EXCLUDE property.
Be Careful

Resource Packing Optimization can make a significant difference in the overall size of the optimized application, but it has two important side effects:
  • It will increase the heap usage of the optimized application,
  • The performance of calls used to access resources will decrease slightly.

If your application is very tight in heap memory, or has a lot of frequent accesses to resources in the .jar file, please consider turning off this optimization.

Tips
  • Generally midlets are written such that the paths used to identify resource files are always given as absolute paths, without using backslashes, and without needing the special directories ('.' and '..'). When the user is certain that the midlet has been written in this way, it is recommended to set the property RESOURCE.PACKING.PARSE.COMPLEX.PATHS to OFF to reduce the optimized application by a further 200-400 bytes.
  • The property RESOURCE.PACKING.EXCLUDE can be used to explicitly exclude a resource file from resource packing. If a particular resource file is known to be accessed frequently, explicit exclusion from the resource packing may improve performance.
  • It is generally recommended to enable this optimization. mBooster will automatically determine if a particular midlet benefits from this optimization. mBooster will also automatically determine the best way to pack resource files, and exclude resource files that do not benefit from packing.
 

Resource packing and heap usage

When optimizing applications with high heap memory usage, the effect of resource packing needs to be considered carefully. On some handsets including Nokia series 40, the loading of a resource from a pack file requires a substantial amount of free heap memory, roughly equivalent to the size of the pack file. If the required heap memory is unavailable, the optimized application will fail to run on the handset, even though the emulator may still run the application as it may model the handset memory limits inaccurately.

The maximum size of the pack files is configured by setting the RESOURCE.PACKING.MAX.PACK.SIZE property. Setting this property will place an upper limit on the size of the pack files produced by mBooster, and so place a limit on the heap memory required to load a resource from a pack file.

We recommend that when optimizing for heap memory constrained devices such as Nokia Series 40, you thoroughly test the heap usage of your application after mBooster optimization. If the optimized application runs out of heap memory, please consider reducing the value of the RESOURCE.PACKING.MAX.PACK.SIZE property, or in the worst case switching off Resource Packing optimization entirely by setting OPT.RESOURCE.PACKING property to OFF. Typically you should be able to significantly reduce the application size while satisfying heap memory usage, through setting RESOURCE.PACKING.MAX.PACK.SIZE appropriately.



PNG Recompression

Property settings

This optimization is turned OFF by default.
In the property file,
OPT.PNG.RECOMPRESSION=ON turns on this optimization
OPT.PNG.RECOMPRESSION=OFF turns off this optimization
 

PNG Recompression employs Innaworks' superior mBoosterZip compression algorithm to reduce the size of the PNG files. Specifically this optimization recompresses the IDAT data chunks present in PNG files.

By default it removes all unnecessary information from each PNG file, keeping the compulsory chunks and tRNS (transparency) chunk.

By default, PNG Recompression is turned off, due to the generally long execution time for the recompression process. The mBoosterPng command-line tool is the equivalent of this step, and can be used separately to mBooster to prevent the need to recompress the PNG files during every execution of mBooster.

To control the files that will be recompressed by this optimization, and for other configuration options, see this set of properties.
Be Careful

A possible coding practice for J2ME applications is to hard code the size of PNG files into the application itself. When your application is coded to be dependent upon the size of your PNG files, PNG Recompression must be turned OFF, or otherwise the PNG files affected must be explicitly excluded through the PNG.RECOMPRESSION.EXCLUDE property. Using mBoosterPng prior to mBooster and ensuring the application expects the correct size for PNG files is the suggested approach.



M3G Recompression

Property settings

This optimization is turned OFF by default.
In the property file,
OPT.M3G.RECOMPRESSION=ON turns on this optimization
OPT.M3G.RECOMPRESSION=OFF turns off this optimization
 

M3G Recompression employs Innaworks' superior mBoosterZip compression algorithm to reduce the size of the M3G files.

By default, M3G Recompression is turned off, due to the generally long execution time for the recompression process. The mBoosterM3G command-line tool is the equivalent of this step, and can be used separately to mBooster to prevent the need to recompress the M3G files during every execution of mBooster.

To control the files that will be recompressed by this optimization, and for other configuration options, see this set of properties.

Be Careful

A possible coding practice for J2ME applications is to hard code the size of M3G files into the application itself. When your application is coded to be dependent upon the size of your M3G files, M3G Recompression must be turned OFF, or otherwise the M3G files affected must be explicitly excluded through the M3G.RECOMPRESSION.EXCLUDE property. Using mBoosterM3G prior to mBooster and ensuring the application expects the correct size for M3G files is the suggested approach.



Redundancy Elimination

Property settings

This optimization is turned OFF by default.
In the property file,
OPT.VN=ON turns on this optimization
OPT.VN=OFF turns off this optimization
 

Redundancy Elimination removes expressions that has multiple occurrences in a method. By removing duplicate expressions Redundancy Elimination will increase the performance and may reduce the size of the application. It is important to point out that field reading and array loading are computationally expensive, and these could be automatically removed by mBooster.

Redundancy Elimination is able to remove redundant
  • Arithmetic expressions
  • Field reads
  • Array loads
Original code
void someMethod() {
    int x = ...
    int y = ...
    int z = (x+y);
    doSomeCalculation(x+y);

    Player player = ...;
    NonPlayerCharacter assassin = ...;
    Weapon knife = ...;
    if (assassin.power > 0) {
        player.doDamage(assassin.power * knife.power);
    }

    
    int[] intArray = ...
    for (int i = 0; i < intArray.length; i++) {
        intArray[i] = ....
        doSomething(intArray[i]);
        doSomethingElse(intArray[i]);
    }
}

When Redundancy Elimination is turned on and it is determined that the replacement is cost effective, mBooster optimizes the above code fragment to the following equivalent code, with the following replacements:

  • x+y is now replaced by z
  • assassin.power is replaced by a new local variable assassinPower
  • intArray[i] is replaced by a new local variable elementValue
Equivalent optimized code
void someMethod() {
    int x = ...
    int y = ...
    int z = (x+y);
    doSomeCalculation(z);

    Player player = ...;
    NonPlayerCharacter assassin = ...;
    Weapon knife = ...;
    int assassinPower = assassin.power;
    if (assassinPower > 0) {
        player.doDamage(assassinPower * knife.power);
    }

    
    int[] intArray = ...
    for (int i = 0; i < intArray.length; i++) {
        int elementValue = ...
        intArray[i] = elementValue;
        doSomething(elementValue);
        doSomethingElse(elementValue);
    }
}

Be Careful
  • Redundancy elimination is currently turned OFF by default.
  • The current version of Redundancy Elimination is by design very conservative. Redundancy Elimination will be considerably extended in the future.
  • Under some conditions, turning on Redundancy Elimination will increase the compressed code size, though it will offer performance advantages.
 
Tips
  • Turn on Redundancy Elimination if there are many repeated expressions in your application, and performance is important.
  • Manually removing redundanies is generally not advisable, as it could significantly reduce the readability of the source code.
 



Local Variable Optimizations

Property settings

This optimization is always turned ON.
There is no control property file setting.
 
mBooster automatically analyzes the uses and definitions of all local variables and will reuse variables where possible.
Original code
void someMethod() {
    int locationX = ...
    int locationY = ...
    doSomeCalculation(locationX);
    doSomeOtherCalculation(locationX, locationY);

    // locationX is not used from here onwards, locationY is used further down
    int damage = ...
    if (damage > 10) {
        ...
    }
}

mBooster recognizes that locationX and damage can be merged into a single local variable, and optimizes to the following equivalent code.

Equivalent optimized code
void someMethod() {
    int mergedVariable = ...
    int locationY = ...
    doSomeCalculation(mergedVariable);
    doSomeOtherCalculation(mergedVariable, locationY);

    // locationX is not used from here onwards, locationY is used further down
    mergedVariable = ...
    if (mergedVariable > 10) {
        ...
    }
}

mBooster performs many other optimizations on local variable usages. Another commonly performed manual optimization is to nest subexpressions deeply to eliminate the definition of local variables. mBooster also automates this optimization.
Original code
void someMethod() {
    Pos myPos = getMyPos();
    Pos monsterPos = getMonsterPos();
    int dist = getDistance(myPos, monsterPos);
}

mBooster recognizes that the expressions can be nested, and will automatically transform the code to:

Equivalent optimized code
void someMethod() {
    int dist = getDistance(getMyPos(), getMonsterPos());
}



Stackmap optimizations

Property settings

This optimization is always turned ON.
There is no control property file setting.
 

mBooster performs a series of optimization with the goal of minimizing the size of the stack maps generated by the preverifier.



Dead class, field and method elimination

Property settings

This optimization is always turned ON.
There is no control property file setting.

mBooster has the ability to determine exactly what classes, fields and methods are required for the proper operation of your program. mBooster will automatically remove from your program any classes, fields and methods that are not required, and hence reduce the size of your program.



Dead and unreachable code elimination

Property settings

This optimization is always turned ON.
There is no control property file setting.
 

mBooster has the ability to determine code fragments that can never be executed, or code fragments that can be executed but have no effect. mBooster will automatically remove these code fragments.

Previous pageContentsNext page