This is the presentation from the Ask the Expert: App performance on Series 40 phones webinar. In this presentation, Michael Samarin of Futurice, provides an overview to the key issues that should be considered when designing Series 40 Java apps for optimum performance. Michael covers issues such as selecting the technology for your GUI, memory considerations, obfuscation, objects, variable, and caching among others.
WordPress Websites for Engineers: Elevate Your Brand
Optimize app performance on Series 40 phones
1. ASK THE EXPERT:
APP PERFORMANCE ON SERIES 40
PHONES
Michael Samarin
Director,
Developer Training and Evangelism
Futurice
2. INTERACTIVE SESSION
• This is special webinar “Ask the Expert” on all things related to
apps performance on Series 40
• It is interactive, and your questions are driving discussion
• You can ask questions right now in the chat window, or for future
sessions send your questions in advance to
webinar.experts@nokia.com
• Today, we will go first through questions we have received and
F.A.Q. and then will switch to interactive mode
4. LCDUI FORMS
» Fast, simple and standard way of making UI.
» On full touch Asha very attractive looking and have huge UX improvements.
» Not as fast as Canvas. Animation on a Form is much slower than on a Canvas,
and there is no way to influence the vertical scroll position, animate transitions
between screen, or shift to a full screen view. You can, however, slightly
increase the performance when changing screens by using just one Form and
re-populating it with new Items.
» http://www.developer.nokia.com/Resources/Library/Full_Touch
5. CANVAS
» Highly customizable way of making UI.
» You have to take care of render timing yourself, or you can use Nokia’s
FrameAnimator class to quickly create effects such as kinetic scrolling.
» Any part of your code can call Canvas.repaint() to signal that painting should
occur soon.
» The most important performance tip for navigating through a Canvas-based
UI is to implement your own View class to represent each screen, and paint all
Views on one Canvas rather than switching from one Canvas to another,
which can be slow and does not give you the possibility of animating the
transition for smooth effect.
6. GAMECANVAS
» GameCanvas is double buffered with more control over the painting cycle and
threading.
» Unlike Canvas, you should create your own Thread, which calls
GameCanvas.paint() directly to fill the graphics buffer, and then
GameCanvas.flushGraphics() to instantly blit the graphics buffer onto the
screen.
7. LWUIT
» LWUIT (Lightweight User Interface Toolkit) is a toolkit for creating SWING-like
applications without some of the complexity of SWING.
» Like Form, it offers basic components, but it adds to this better layouts, styles and
theming, bundling own fonts into your application, and animated screen transitions.
» LWUIT is implemented on top of a Canvas, but it is a large and complex library written
to be a general purpose replacement for the default UI on many different phones.
» LWUIT and the associated themes and any fonts you include quickly make your JAR file
grow quite large.
» http://projects.developer.nokia.com/LWUIT_for_Series_40
8. HEAP MEMORY
» On Series 40 only from 2 to 4 MB.
» Instances of classes (objects) and primitive types are created in the
heap.
» Total number of methods in classes loaded by JVM has a direct
impact on how much heap space is left for other data. These
memory allocations are permanent for the runtime of the
application and are not dynamically unloaded by the JVM once a
class is no longer in use.
9. RECURSIVE ALGORITHMS AND STACK MEMORY
» Variables passed as arguments to a method are passed on the current thread’s
stack. Method variables of primitive types are also allocated on the stack.
» Recursive algorithms are algorithms where a method calls itself in a loop to
complete a task. As a result, they create multiple stack frames.
› They use a lot of stack memory. The same method is called repeatedly, and only as the application completes
does it unwind the queued stack frames. This extra stack memory is often not useful, and stack memory per
thread is limited and such heavy stack use may well cause an OutOfMemoryException well before you are
actually out of heap memory.
› Recursive algorithms can be slow. Each method call includes a certain amount of overhead, which is not really
necessary since a recursive algorithm can be unwound into a non-recursive equivalent loop that does not include
the relatively heavy method call.
10. COMPILE TIME OPTIMIZATION AND OBFUSCATION
» Provides basic “free” optimization
» Fixes code redundancy and pre-calculate things whenever possible
» Minimizes memory usage
» Should be last step in building apps – takes time and makes
debugging difficult
» Doesn’t fix wrong architecture
11. OBFUSCATION EXAMPLE: BATTLE TANK
https://projects.developer.nokia.com/JMEBattleTank
• JAR File size decreased by 4%
(889 -> 852 kB)
• RAM usage decreased by 14%
(161 -> 138 kB)
12. ARCHITECTURE CHANGES
» Carefully consider architecture of your drawing loop and input
loops and decouple them whenever possible.
» Example: panorama drawing and sensor driving loop.
» Original example:
» http://www.youtube.com/watch?v=PfW4BVHgri8
» After optimization:
» http://www.youtube.com/watch?v=xSRYVYrNNMI
13. WEAKREFERENCE OBJECT CACHING
» Best pattern for using all available heap memory, but never running into the
dreaded OutOfMemoryError.
» CLDC 1.1 WeakReference
» When an object is referenced by a WeakReference, and not using traditional
Object pointers, this is a signal to the garbage collector that is has permission to
collect the object if memory is running low.
» You have to maintain own HashTable of Objects
» To understand this pattern better look at Tantalum 3:
http://projects.developer.nokia.com/Tantalum
14. RENDER CACHING
» One of the common performance needs is to make your application paint, in
particular scroll, smoothly and quickly.
» You can paint items each into their own Image, keeping that pre-painted Image in a
cache, and reusing it as the object moves around the screen. Essentially,
WeakReference cach of pre-painted Images.
» Can achieve dramatic FPS increase, like in this example from 3 to 12 on Asha 305:
» http://www.youtube.com/watch?v=Z2QcnhROFGc
» To understand this pattern better look at Tantalum 3:
http://projects.developer.nokia.com/Tantalum
15. HASH ACCELERATION
» Some iterative algorithms are slow. Proper usage of collections
types of data structures can increase performance.
» Vector.contains() is very slow, but Hashtable.containsKey() is very
fast. Reconsider your algorithms to use Hashtables.
» Usage can be found in very surprising places. For example,
Font.stringWidth() is slow, but necessary for drawing multiline text
on Canvas. Creating a Hashtable with the width in each character
you have used in the Font can transform this into a fast operation
and increase Canvas.paint() speed.
16. CONSTANTS
» We can give the compiler and Proguard more opportunities to optimize the code at
the compile step, and this will also give the ARM processor opportunities for
handling these variables with more efficient byte codes.
private static int loopCount = 10;
private static long startTime = System.currentTimeMillis();
private static boolean enableImages = true;
Should be
private static final int LOOP_COUNT = 10;
private static final long START_TIME = System.currentTimeMillis();
private static final boolean ENABLE_IMAGES = true;
17. PRIMITIVES
» Use int instead of short, byte or long.
for (int i = 0; i < 3000000; i++) {
short/int/long a = 123;
short/int/long b = -44;
short/int/long c = 12;
a += c;
b += a;
c *= b;
}
Average times spent in loops on Nokia Asha 305 (obfuscated):
int: 710 (580) ms
short: 900 (850) ms 50% slower
long: 1450 (1150) ms 100% slower
18. STATIC
» Generally static methods and variables should be faster. Oddly, with
some combinations of ARM and JVM, instance accesses are slightly
faster.
for (int i = 0; i < 1000000; i++) {
staticMethod();
} Average times spent in loops on Nokia
for (int i = 0; i < 1000000; i++) { Asha 305 (obfuscated):
nonStaticMethod();
}
nonStaticMethod: 570 ms
private static void staticMethod() {
b++; // static variable staticMethod: 680 ms 20% slower
}
private void nonStaticMethod() {
a++; // instance variable
}
19. PERFORMANCE SUMMARY
» Compare Algorithms
› Talk to colleagues and pick the best algorithm; having the best possible
algorithm is the most effective way to optimize performance.
» Simple Architecture
› Keep your architecture simple and to the point without extra layers of method
calls or objects for artificial abstraction. Mobile front end code does not last for
ever, so over-engineering and excessive abstraction into multiple classes will
slow you down compared to simple use of variables.
20. PERFORMANCE SUMMARY
» Manage Memory with WeakReference Caching
› Avoid memory problems by always accessing image data in
memory using a WeakReference Cache.
› Create a type of virtual memory by duplicating the
WeakReference cache contents in Flash memory (Record
Management System) so that you can quickly recover items
which are no longer available in RAM.
21. PERFORMANCE SUMMARY
» Use micro-optimizations of the code as habit
› Know the rules of micro-optimisation for memory performance,
logic and calculations. Include those as you develop, but trust
Proguard to add the finishing touches.
› Help Proguard by making everything possible final or static final.
Avoid static variables in high performance loops as they are
slower than instance variables.
22. PERFORMANCE SUMMARY
» Profile your app towards the end of project
› Profile your application in an emulator.
› Also test the actual run-time of critical code sections on the
phone using System.currentTimeMillis() to see and carefully
measure the effects of your code changes.
23. THANK YOU!
Want to learn more?
www.developer.nokia.com
Michael Samarin, Director of Developer Training and Evangelism, Futurice