Saturday, January 9, 2010

LWUIT Is Faster Than LCDUI For Networking (at least on Samsung)

Readers of this blog should be familiar with the drill, operator goes ape sh*t over the performance of your application on a specific device and you get called in to do a weekend session on trying to figure out WTF is wrong???

Where do you even start?

I got a similar call over this weekend where an application under evaluation at an operator just didn't perform as expected for file download on Samsung devices (although is doing quite fine for other devices). Well, obviously LWUIT had nothing to do with it since its file downloads and unrelated to UI... Right?

I tried practically everything I could think of, from thread priorities to sleeps in various strategic places... Nothing.

Then I decided to start fresh, I created a pure LCDUI test case for downloading and got a respectable 80kbps download speed. When switching the test case UI to unthemed LWUIT I got a 140kbps download speed...

I always say LWUIT is fast but this REALLY floored me! There was practically no UI involved and the issue here was download speed rather than the UI speed, what was going on???

It turns out that the Samsung devices have a different threading model, even if you assign priorities to threads the background threads do tend to grab CPU even from networking (as opposed to e.g. Sony Ericsson where a network operation can stutter the UI). This behavior resulted in unbelievable performance difference between the LCDUI and LWUIT test case, even though the test is supposed to be completely IO bound.

Armed with this knowledge I did the following in the code:
  1. Raised the priority of the network thread when its working on important downloads (when showing a blocking progress bar).
  2. Reduced repaints and animations, e.g. an animate method that returns true even when a glass pane was drawing progress on top of it.
  3. I made another animate method refresh less frequently.
These changes coupled with some minor tunings got me far better performance which I can probably improve further.

Lesson learned: LWUIT's EDT thread spends allot of time sleeping and is very highly optimized, possibly more so than some LCDUI implementations. This seems like a small thing but in some devices its more important than others.

To optimize networking on Samsung devices don't think so much about networking, think about the threads you have in the background.

Having a single thread for all your IO/Networking is a good practice when writing mobile applications (obviously a single thread separate from the EDT!). This policy which was already in place had made my life very easy when debugging and optimizing issues since there was only one place to look.

Last but not least, its very difficult to debug performance problems. Its more guesswork than anything else since devices just don't give us any proper profilers or similar tools that we might have on the desktop. They also behave differently than you would normally expect (case in point above). Currently the best advice I can give with such problems is: Isolate a test case and start growing it until you reproduce and truly understand the problem.

Saturday, January 2, 2010

Tensile Drag, Centered Lists And Faster Slide

Running ahead I often forget that not everyone monitors our SVN commits so you don't all follow the latest and greatest in LWUIT (BTW to do so just go to the project mailing lists and subscribe to the commits mailing list to receive detailed commit notifications).
Three cool new things made their way into LWUIT two of which relate to touch support. The first is tensile drag demonstrated in the video to your right, this provides the feel of reaching the edge of the screen in a more physical way. This feature is now enabled for all LWUIT widgets seamlessly.
We now also support dragging on a list which is fixed on the screen vertically or horizontally (such as a carousel), this was ridiculously hard to implement and a long standing bug in our issue tracker. Fixed lists for those of you who haven't played with them, allow a developer to place the focus in a single point (top, bottom or center) and have the list scroll without the focus moving. This feature is essential for the spinner support and also allows very elaborate cool UI's.

Last but possibly most important is the fast slide transition support, some devices are relatively slow to render elaborate graphics (e.g. fonts). S60 specifically is very slow in this regard (reasonably justified since its fonts are quit crisp), LWUIT is quite efficient in font rendering however when running a slide transition rendering these fonts for every frame often bogs down the system. LWUIT now has a "fast slide" transition within the common transitions class that slides two images of the forms rather than the actual forms. This is noticeably faster on S60 devices but is also reasonably smoother on other devices.

This feature isn't enabled by default for two major reasons, the first is its higher RAM requirements and the second is that it breaks the ability to slide translucent/rounded menus/dialogs. However, if you don't intend to use these it might be worthwhile to switch to this transition for a smoother feel.

Monday, December 21, 2009

Nuux LWUIT Nightlife Social Application

Ben just posted to the LWUIT mailing list about the nuux application entering beta.

Nuux is a nightlife jukebox with social networking features. For more details you can visit nuux.net or try out the application on m.nuux.net.

Tuesday, December 15, 2009

LWUIT 1.3 Released

With great pleasure, the LWUIT team is announcing the GA release of Lightweight UI Toolkit (LWUIT) 1.3.

LWUIT is a UI library that is bundled together with applications and helps content developers create compelling and consistent Java ME applications. LWUIT supports visual components and other UI goodies such as theming, transitions, animation and more.

Key features for the current release:
  • Bidi support (contributed by Telmap) - allows using LWUIT with Right To Left languages such as Arabic, Hebrew
  • Lightweight Virtual keyboard support - allowing for customizable touch screen input
  • Pixel based scrolling - allowing scroll to work as expected even when components/containers exceed screen bounds and not just for focusable components
  • Table layout and table component - allowing complex tabular UI's including support for features such as spanning rows/columns
  • Tree component - supporting nested elements and expanding
  • Spinner component for date, time and numeric input within a range
  • Reimplementation of the ComboBox widget
  • SVG Support integrated into the Theme Creator (formerly LWUIT Designer/Resource Editor)
  • Touch device improvements: button menus, improved kinetic scrolling, tactile touch (vibration on touch)
  • Resource file specification
  • Redesigned the list renderer "rendering" logic so that it paints the backgrounds of the renderers first, and then the selection and foreground.
Please visit http://java.sun.com/javame/technology/lwuit/ for more information


On a related note, Thorsten just published further detailed instructions for using LWUIT on the blackberry and Android in his website.

Tuesday, December 8, 2009

Spinning It Round And Round

Spinner is a component we have been postponing since before the 1.0 release of LWUIT, this delay has finally come to an end with the new release of the Spinner component into SVN joining the Tree/Table who are all major features for the 1.3 release.
The Spinner is mostly interesting because it is a composite component that mashes together a list and a text field to create a very unique input method that has some of both. It allows users to select from what is possibly a huge list (not infinite but still pretty huge), of numbers, dates or times. It allows users to type parts of the values or the entire values into the UI for fast searches within the list similar to the searchable list I recently blogged about.

The Spinner achieves such huge lists by creating its own ListModel and using a formula to calculate values on the fly, a renderer is used to display the list as a user would expect it to appear (date/time). The text field is painted in the appropriate location for the date/time input and its values are directly parsed into place.

The source code of the Spinner can be a great starting place to understand how to deeply manipulate such LWUIT components.

The video to the right was created with the four basic spinners. Notice that a spinner normally accepts min, max, current and step size values. For date these are in milliseconds since epoc and for time it it in seconds since midnight.
Form form = new Form("Spinners");
Spinner integerSpinner = Spinner.create(0, 1000, 100, 10);
Spinner decimalSpinner = Spinner.create(0.0, 100.0, 17.75, 0.05);
Spinner timeSpinner = Spinner.createTime(0, 24 * 60 * 60, 10 * 60 * 60, 60, true, false);
Spinner dateSpinner = Spinner.createDate(System.currentTimeMillis() - 1000 * DAY,
System.currentTimeMillis() + 1000 * DAY, System.currentTimeMillis(),
'-', Spinner.DATE_FORMAT_MM_DD_YYYY);

form.setLayout(new TableLayout(4, 2));
form.addComponent(new Label("Integer"));
form.addComponent(integerSpinner);
form.addComponent(new Label("Decimal"));
form.addComponent(decimalSpinner);
form.addComponent(new Label("Time"));
form.addComponent(timeSpinner);
form.addComponent(new Label("Date"));
form.addComponent(dateSpinner);
form.show();

Wednesday, November 25, 2009

Ni Hao LWUIT: Chinese Blog By Max Mu

Max Mu who you might recall as the developer who ported Sun's open source Phone ME VM to the PSP, has started a LWUIT blog in Chinese.
Chinese speakers should definitely check it out!

Tuesday, November 24, 2009

Building A Project On The BlackBerry

Update 2: The Netbeans link within the body died a while back. Updated instructions for 6.7 and newer are available here.

Updated: I forgot to add the main method and UiApplication section. It is now part 9 of the instructions.

While Thorsten & myself wrote build instructions for the BlackBerry in the forum/mailing list in the past they are somewhat outdated by now and aren't as easy to find using Google. So here is a step by step guide on porting to the BlackBerry devices with some explanations of the Caveats.

The standard LWUIT won't work on the Blackberry since it references API's such as 184/226, notice that LWUIT doesn't need or use these API's when they are not available! On the Blackberry device the very reference to these API's will cause the application to fail. Furthermore, as I explained in a previous post, Blackberry devices have some "issues" when using classes compiled without the RIM toolchain and LWUIT isn't compiled with the RIM toolchain.
Last but not least, the performance and user experience of the MIDP based LWUIT on Blackberry isn't very good...

The solution for all these issues is to use the RIM API's, which unfortunately means you need to create two separate versions of your application (3 if you need blackberry Storm support) .

I won't go into too many details on the BlackBerry devices, but a couple of years ago they introduced the Storm device which was their first touch screen device (featuring a click screen). Supporting the Storm requires importing classes of the API that aren't supported in older versions of RIM's API, hence Storm compatibility requires using a relatively new BlackBerry OS that most users don't have.
So you will need two builds and two blackberry Java Development Environments (JDE's) if you need to support Storm.

The instructions bellow are also geared towards the NetBeans IDE and Ant build.

LWUIT currently has two maintained BlackBerry ports, one created by Thorsten & another created by myself. Each has its advantages and you can easily go back and forth between them. Since I used NetBeans I will explain based on my port but you can easily replace the content of the src directory with Thorsten's port and it should be pretty seamless.

A standard LWUIT MIDlet should work fine on a RIM device using the ports, however RIM also offers support for a CLDC application. Using this approach tends to provide improved performance/security handling for RIM although its completely optional.

  1. Download the JDE versions, I recommend 4.2.x and 4.7.x (for Storm support).
  2. Follow the NetBeans BlackBerry knowledge base article to add the JDE versions as platforms to NetBeans (no need to follow the part about editing the build.xml).
  3. Fetch the LWUIT sources from SVN and open the BlackBerry project. Clean & Build the project (notice that you MUST clean & build, a plain build will often fail since the RIM port needs to replace some classes from LWUIT).
  4. If using storm as well, change the configuration of the Blackberry LWUIT port to "touch" and again clean & build.
  5. Download the BB ant tasks which are much easier to work with than the approach taken by the knowledge base article.
  6. Add "configurations" to the NetBeans project for BlackBerry and BlackBerryTouch. Set them to use the appropriate JDE Platforms.
  7. In the blackberry configurations add an "Ability" called RIM. This will allow you to use #ifdef RIM
    rather than #ifdef BlackBerryTouch && BlackBerry
    (yes, I can't stand #ifdef's but they are better than just copy and pasting the entire code and with RIM we don't have a choice).
  8. In the libraries for the project add both LWUIT & the appropriate blackberry project. Make sure to add the touch JAR only to the touch (Storm) configuration and the standard jar to the other BlackBerry configuration.
  9. If you are building a CLDC UiApplication add the following to your MIDlet class definition (instead of extends MIDlet):
    public MyMIDlet extends //#ifdef RIM
    net.rim.device.api.ui.UiApplication
    //#else
    //# javax.microedition.midlet.MIDlet
    //#endif
    {

    Then add this to the body of the MIDlet:
    //#ifdef Blackberry
    public static void main(String[] argv) {
    new MyMIDlet().startApp();
    }
    //#endif

    You might want to also add similar methods for notifyDestroyed/platformRequest:
    public void notifyDestroyed() {
    System.exit(0);
    }
    public void platformRequest(String s) {
    net.rim.blackberry.api.browser.Browser.getDefaultSession().displayPage(s);
    }

  10. Open the build.xml file of your NetBeans project and add the following, update the paths and names marked in bold (notice this is geared towards a CLDC UiApplication, you might need to modify this slightly for a MIDlet):
    <target name="post-init">
    <available file="${platform.home}/bin/rapc.exe" property="do.rapc">
    <available file="${platform.home}/simulator/9500.bat" property="bbtouch">
    <condition property="jpda.port" value="8000">
    <isset property="do.rapc">
    </isset>
    </condition>

    <target name="post-preprocess" depends="copyBBSources,copyBBTouchSources">
    </target>

    <typedef resource="bb-ant-defs.xml" classpath="bb-ant-tools.jar">
    <target name="bbbuild" description="blackberry build" depends="init,copyBBSources,copyBBTouchSources">
    <echo message="Compiling ${preprocessed.dir}"></echo>
    <mkdir dir="${dist.dir}/bbant">
    <rapc verbose="true" output="${name}" jdehome="${platform.home}" import="${platform.bootclasspath}" destdir="${dist.dir}/bbant/" noconvert="true">
    <src location="${basedir}/${preprocessed.dir}">
    <jdp title="Vendor" version="1" type="cldc" icon="${basedir}/src/icon.png" />
    </jdp>
    <!-- sigtool jdehome="C:\Program Files\Research In Motion\BlackBerry JDE 4.7.0" codfile="${dist.dir}/bbant/${name}.cod" password="" / -->
    <alx destdir="${dist.dir}/bbant" filename="${name}.alx">
    <application id="AppName">
    <codset>
    <fileset dir="${dist.dir}/bbant" includes="*.cod">
    </fileset>
    </codset>
    </application>

    <mkdir dir="${dist.dir}/bbant-final">
    <jadtool description="desc" id="appId" input="${dist.dir}/${dist.jad}" destdir="${dist.dir}/bbant-final">
    <fileset dir="${dist.dir}/bbant" includes="*.cod">
    </fileset>
    </jadtool>

    <target name="copyBBTouchSources" if="bbtouch">
    <echo message="Copying blackberry touch sources"></echo>
    <copydir forceoverwrite="true" src="$%7Bproject.BlackberryPort%7D%5Cbuild%5Ctouch%5Cpreprocessed" dest="${basedir}/${preprocessed.dir}">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/M3G.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/SVGImage.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/animations/Transition3D.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/impl/midp/SVGImplementation.java">
    </touch>

    <target name="copyBBSources" if="do.rapc">
    <echo message="Copying blackberry sources ${preprocessed.dir}"></echo>
    <copydir src="$%7Bproject.LWUIT%7D%5Csrc" dest="${basedir}/${preprocessed.dir}">
    <copydir forceoverwrite="true" src="$%7Bproject.BlackberryPort%7D%5Cbuild%5Cpreprocessed" dest="${basedir}/${preprocessed.dir}">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/M3G.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/SVGImage.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/animations/Transition3D.java">
    <touch file="${basedir}/${preprocessed.dir}/com/sun/lwuit/impl/midp/SVGImplementation.java">
    </touch>

    <target name="post-jar" if="do.rapc">
    <rapc verbose="true" output="${name}" jdehome="${platform.home}" import="${platform.bootclasspath}" destdir="${platform.home}/simulator/" noconvert="true">
    <src location="${basedir}/${preprocessed.dir}">
    <jdp title="Vendor" version="1" type="cldc" icon="${basedir}/src/icon.png" />
    </jdp>
    </src>

    <target name="post-clean">
    <delete failonerror="false">
    <fileset dir="${platform.home}/simulator">
    <include name="**/${name}.*">
    </include>
    </fileset>
    </delete>
    </target>