BlackBerry Java: Arithmetic Comparisons
May 2nd, 2009This investigation took me longer than I had hoped to get to a conclusion, mainly because the results I was getting weren’t matching my expectations. I started off by comparing the speed of arithmetic calculations between the BlackBerry Java’s native float implementation and its static class implementation for fixed point math, Fixed32.
When first faced with the need to store fractional values, I gravitated towards the Fixed32 class for two reasons; the first being that I’ve always had to use a fixed point implementation when developing mobile application as floats and doubles are not usually available. The second reason was that I believed the Fixed32 class existed for a reason, that reason being that the float implementation was so horribly slow that this additional fixed point implementation had to exist to compensate.
It turns out that the Fixed32 class is legacy code of the BlackBerry platform, implemented early on before floats and doubles could be properly supported. And, the truth was that the float multiplication and division implementations are faster than the Fixed32 implementation’s, though float addition and substraction was still slower due to the fact that Fixed32 is developed to use the integer addition and subtraction operators with no other processing.
These were the preconceptions that I had when developing my own test. The problem that was hanging me up was that I was seeing better performance out of the float’s add and subtract operators than the Fixed32’s use of the integer operators. I couldn’t figure out how this could be. Look how simple this code is, what could I be doing wrong?
public class TestConstants { // ... public final static int X_MUL_DIV_VALUE = Fixed32.parseFixed32("1.84"); } public class Fixed32Add extends CodeBlock { // ... public void run() { int xResult = 0; for(int i = 0; i < TestConstants.NUM_OPERATIONS; i++) { xResult += TestConstants.ADD_VALUE_X; } } }
So I decided to expand the test and cover arithmetic with all native numerical types, the additional types being byte, short, long, and double. Once I did that, it became clear what the problem was. Without Fixed32 being involved, the integer addition/subtraction operators were about 3 times faster than the floating point operator.
There was a sneaky little issue that is nearly impossible to see if you’re not looking for it. Here’s the code change first:
public class TestConstants { // ... public final static int X_MUL_DIV_VALUE = Fixed32.parseFixed32("1.84"); } public class Fixed32Add extends CodeBlock { // ... public void run() { int xResult = 0; int value = TestConstants.ADD_VALUE_X; for(int i = 0; i < TestConstants.NUM_OPERATIONS; i++) { xResult += value; } } }
The compiler handles the final variables, replacing each reference to the final variable with the code on the right of the declaration, resulting in the parse function being called for every iteration of the loop. As I said, sneaky. It’s something to be aware of when declaring final variables. If you have a native value, the inline processing performed on final variables can be quite beneficial. However, with objects and function calls to generate the value of the final variable, it can result in additional processing and memory that hides behind a mask that makes it hard to see. Just keep it in mind.
Anyway, below are the result tables, one for each device (Curve, Bold and Storm, NUM_OPERATIONS = 5000). As stated at the beginning, float multiplication/division is faster than Fixed32 multiplication/division.
BlackBerry Curve 8320
| Variable Type | Add/Sub (ms) | Mult (ms) | Div (ms) |
| Fixed32 | 204 | 1372 | 1788 |
| float | 700 | 548 | 1184 |
| double | 1104 | 824 | 4376 |
| long | 260 | 260 | 528 |
| int | 196 | 200 | 248 |
| short | 240 | 220 | 272 |
| byte | 220 | 232 | 272 |
BlackBerry Bold
| Variable Type | Add/Sub (ms) | Mult (ms) | Div (ms) |
| Fixed32 | 153 | 597 | 776 |
| float | 317 | 242 | 550 |
| double | 514 | 366 | 1931 |
| long | 114 | 117 | 225 |
| int | 96 | 90 | 114 |
| short | 102 | 102 | 125 |
| byte | 104 | 107 | 127 |
BlackBerry Storm
| Variable Type | Add/Sub (ms) | Mult (ms) | Div (ms) |
| Fixed32 | 135 | 863 | 1089 |
| float | 379 | 293 | 694 |
| double | 599 | 420 | 2424 |
| long | 150 | 155 | 284 |
| int | 131 | 137 | 162 |
| short | 150 | 150 | 170 |
| byte | 146 | 144 | 172 |
To conclude, make conscious choices about which variable types are right for your arithmetic needs. If you plan to do a lot of addition and subtraction with fractional outcomes, the Fixed32 class may still be your best bet (if accuracy is not all that important). However, you’re better off using native floats with multiplication and division. Finally, be careful with final variables. They’re built in a way to cause problems and hide inefficiencies if care isn’t taken.

August 30th, 2009 at 1:14 pm
[...] (see next post) and wondering about performance of double/float/Fixed32 arithmetic I came across this post on Blurry Words, which is exactly what I was looking [...]