Titanium Mobile: Flexibility vs. Performance

Last week I had the pleasure to give a talk at the WhyMCA Italian Mobile Developer Conference. The title of the talk is “Titanium Mobile: Flexibility vs. Performance”. Despite being structured as a quite technical speech, at it’s heart I consider it a “philosophical” one, since its message is highly related to why I think the approach to cross platform mobile development and code portability provided by Titanium is, albeit always perfectible, the right one. In this post I’d like to expand a bit on the motivations behind this line of thinking.

Titanium isn’t a write-once-run-everywhere platform. As Appcelerator’s guys use to say, its aim is to be a write-once-adapt-everywhere tool, since, while using a common high level language and API, it enables the exploitment of platform specific features when needed. This philosophy is clearly visible in the API, as we have entire sub-namespaces dedicated to either iOS, or Android. This allows adapting our mobile applications to the platforms where they’re executed, thus avoiding a write once, suck everywhere effect. Moreover, the possibility to develop custom native extensions to the framework opens up a wide range of development scenarios, ideally allowing us to create user experiences that are practically undistinguishable from those of applications developed with native SDKs.

My point of view on this kind of approach to cross platform portability has its roots in the work I took over during 5 years as a researcher, where I explored the boundaries of flexibility (in terms of ease of development and cross platform portability) and performance in the field of network processing architectures. If you really have nothing better to do, you can check out my PhD dissertation thesis dating back to the beginning of 2009 for additional details.

While at a completely different scale, in mobile application development we face challenges that are very similar to those that passionated me during my research:

  • heterogeneous and incompatible mobile device platforms and OSs
  • while native capabilities are quite homogeneous across platforms, UIs are not
  • each platform must be programmed with it’s own SDK, each one based on a different language (e.g. Java for Android, objective-c for iOS, and so on) - code reuse and portability is impossible
  • we have stringent constraints on the User Experience: apps with a poor UX fail to gain wide adoption

In this scenario, the approach proposed by Titanium is very interesting:

  • It’s based on a high level language that abstracts away the different programming models of the target platforms
  • It provides a very wide and flexible high level API (in contrast to other technologies, like the very recent RubyMotion, which provides just Ruby wrappers around the classes of the iOS Cocoa Touch framework)
  • It’s extensible through natively coded modules for leveraging native features of the target platform

Titanium applications are native by all means anyway, since even if written in JavaScript, they directly rely on native functionality. However, as its API is very general and flexible, allowing to adapt the same macro components to very disparate uses, in some cases this may cause slow downs and not so slick user experiences. It’s quite simple to explain why this happens: when the code implementing an UI component (e.g. a TableView), must be able to adapt to every possible use, we are introducing some amount of overhead, with the result of trading off performance in favor of flexibility.

So, in my presentation, I tried to propose two main lines of thought based on the realistic scenario of performance problems related to the creation and scrolling of a table view. The first line of thought tries to make the point that when we face a performance problem, which in mobile development is frequently a UX problem, we need to go to the root of the issue, by understanding what is causing it. This means the following things:

  • we need to know how the tools we’re using actually work under the hood: Titanium doesn’t use the same JS engine on both iOS and Android. In particular, JavaScriptCore and V8 are very different implementations of JS, the latter being an optimizing JIT compiler, while the former is actually a bytecode interpreter, as JIT compilations is forbidden by iOS
  • As a corollary, relying on some old school micro-optimizations, like caching the length of an array while iterating over it in a for loop, may be actually useless, since if the body of the loop is “fat” enough, I’m quite sure you’re not wasting time in that check. Moreover, if that loop is “hot” enough, V8 will automatically optimize it anyway, by hoisting the access to the array length outside of the loop (check out this video from JSConf 2012: “One day of life in V8” by Vyacheslav Egorov)
  • We need to measure, at first even just in a rough way, in order to find where we are loosing time

This last point raises an alert on the lack of accurate profiling tools that we can productively use for measuring the actual performance of our code. My extensions to Titanium for leveraging the JavaScriptCore profiler are still work in progress, and I’ll hopefully post an update on that story soon.

The other line of thought I pursued, is related to what we can do for increasing the scrolling performance of our table view component. Table views are a critical component in most applications, and those presenting complex row layouts can result in choppy scrolling animations for several reasons. Complex row layouts are actually a problem also when developed natively, however, in Titanium we have much less opportunities for optimizations, as we obviously need to rely on the provided API implementation, which is crafted in a way that enhances flexibility and ease of use for the developer.

In my presentation I propose a short investigation on the reasons that underly a lack of scrolling performance, by using the Instruments Core Animation profiling tools provided with Xcode. Scrolling issues are usually caused by transparent, or non-opaque views, like labels, which make the rendering engine do extra work for computing how superimposed views blend together. Another major pain point (often more important than the former) is represented by views with rounded corners, which need more iterations to be rendered. In this case, a very simple solution is to use image masks: a semi transparent image to be superimposed to the view that needs rounded corners. If the view is an ImageView, the Ti.UI.MaskedImage component does just the right job.

There’s an interesting session from Apple’s WWDC 2010 where these kinds of performance issues are analyzed. The talk is titled “Performance Optimization on iPhone OS”. If you are registered as an Apple developer you can download the video from https://developer.apple.com/videos/wwdc/2010/.

So we come to the center point of my reasoning. If we are not able to fulfill our performance goals by tweaking our use of the standard API, Titanium allows us to implement our performance-critical components as native modules. In other words, we can trade flexibility for gaining performance. For doing so, we must give up some amount of generality and the possibility to reuse our code in other applications by implementing an optimized component that exposes an application-specific semantic: both the API and the implementation of the module will be tailored on the peculiar application and it’s performance requirements.

Following the table view example, on iOS this translates into having tableview rows with a hardcoded layout, possibly with sub-views whose opaque property is set to true on iOS, and so on. Would we still be dissatisfied with the result, we can always rely on the concept of fast-cells, which are tableview cells actually composed by a single view, where all information to be shown is laid out by using low level CoreGraphics drawing primitives. Check out the iOS Boilerplate project and this coding example from Apple for additional information.

Summarizing, what does all this mean? That Titanium Mobile is a tool allowing us to create very complex cross platform mobile applications in a fraction of the time needed to make parallel developments using native SDKs. The possibility to extend the framework with native modules opens up a wide range of development scenarios, enabling both the reuse of existing native libraries, and the optimization of performance-critical portions of the app, when needed.

Is it a panacea? Not really, IMHO. I use Titanium since version 0.8, and despite a visible effort in making it better release after release, even now that version 2.0 is out I think it’s still a bit immature. I still see it somewhat a platform made for hackers, rather than for developers, as without a deep knowledge of its internals it’s often impractical to overcome even trivial issues like a failed build. A quick look at most of the questions on the Q&A forum will suffice to support my point of view on this.

That said, even taking into account the problems, I think Titanium is the right tool every time we are dealing with an application that needs to support both iOS and Android platforms, whose value resides in a rather complex business logic, instead of just in the presentation layer. In these cases, we don’t want to develop, test, debug, and maintain different implementations of the same solution across different platforms. Moreover, being based on a high level abstraction layer (JS language + very flexible API), Titanium allows very quick iterations in the solution space, which is an invaluable feature when we are trying to validate business ideas against unkown markets.

Finally, here you find the slides of my presentation:

Titanium Mobile: flexibility vs. performance from omorandi

Bash One-liner for Renaming High-res Image Files to @2x

This tip may be useful to iOS developers when they’re given a bunch of high-resolution files and they need to rename them with the @2x filename suffix.

Supposing the files are all in the same directory (containing only the files you need to rename), just do this in the terminal:

for file in *; do mv "$file" "${file%.*}@2x.${file##*.}"; done

As a result, the files will all be renamed following the pattern <name>@2x.<extension>.

Profiling Ti Mobile Apps: Is It Possible?

Short answer is: “YES” (at least on iOS - for now), and this post is here to share some very early results for supporting such statement. What’s reported here is just something I started working on in the last few weeks and it’s still a quite long term work in progress.

Profiling tools

Profiling means measuring how much time is spent in every relevant portion of code of an application during its execution, and it represents the first step to be done when searching for spots in the code that can be optimized, in order to achieve better performance. Performing any form of optimization without profiling first is like running a race with blinded eyes.

So, what does it mean profiling a Titanium Mobile application written in JavaScript? What tools do we have? How can we find hotspots in our poorly behaving apps? The reality is that unlike other development enviroments, the Titanium Mobile SDK doesn’t provide any tool for accurately profiling JS apps. When developing for iOS, we can use the Instruments profiling tool provided with Xcode, and the typical results obtained using such tool are shown in the following picture:

in the bottom-right panel we see a list of functions and methods with the associated total time spent executing them. However, while this kind of information gives us a notion on the time spent inside the functions of the framework, the time spent in our JavaScript functions, which are those we probably want to optimize, is completely hidden behind the calls to the functions of the JavaScript interpreter.

On the other hand, developers coming from web development may be used to working with the JS tools provided by the major browsers (e.g. Firebug in Firefox, Chrome & Safari developer tools, etc.), which give us detailed profiling information on the scripts being executed by a web page. For example, the following picture shows the results obtained with the developer tools available with Chrome:

Profiling Ti apps

Since I need to profile a quite complex Titanium Mobile application for finding hotspots in the code that may need to be offloaded to some native modules, I started guessing how could I achieve my goal. As usual, digging into the Ti SDK code helps a lot, and after following the white rabbit in the hole I found the response in the code of the JavaScriptCore interpreter. We always have to remember that Titanium Mobile shares its core engines with Safari and Chrome, i.e. JavaScriptCore and V8 respectively, so any low level feature tied to JS execution available in these browsers is also available in Titanium, moreover all that code is completely available as open source. So, it turns out that most of the features needed for profiling JS code are exactly where they should be, i.e. in the interpreter.

For those who wonder how a profiler works, it’s easy told. The profiler is nothing more than a component that records the time when each function gets called and when it returns. Whenever the interpreter needs to execute a function, it tells the profiler: “I’m going to execute function F, which starts at line X of file at URL Y”. The same just after the execution of the function: “I executed Function F, bla bla”. This allows the profiler to have a clear vision on two very important kinds of information:

  • How function calls are related, i.e. the call graph
  • How much time is spent during the execution of every function

Obviously, the total time spent in a function will also include the time spent in nested function calls, but the profiler keeps track of these situations, in order to give accurate results.

So, during my journey, I managed to build the JavaScriptCore library from scratch and I started tweaking the code in order to be able to start and stop the profiling from the native code of a Titanium application. I had a quite encouraging success a couple of weeks ago and tweeted about it:

Actually I was happy about the integration, but no real profiling data was returned. After studying more deeply the code and a lot of debugging, today I’ve been able to produce a more meaningful profile of a test application, which is composed of a barebone app.js file:

app.js
1
2
3
4
5
6
7
8
9
10
11
12
Ti.include('included.js');

function launch_test1() {
    test1();
}

function launch_test2() {
    test2();
}

launch_test1();
launch_test2();

and a module containing a couple of functions performing some useless math tasks. The module is suitable to be either included via Ti.include(), or required through CommonJS require():

included.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var exports = exports || {};

function test1() {
    var sum = 0;
    for (var i = 0; i < 1000000; i++) {
        sum = sum + Math.cos(i);
    }
    Ti.API.info('result 1: ' + sum);
}

var test2 = function() {
    var sum = 0;
    for (var i = 0; i < 1000000; i++) {
        sum += Math.sin(i/1000);
    }
    Ti.API.info('result 2: ' + sum);
};

exports.test1 = test1;
exports.test2 = test2;

Please note that the two test functions in included.js are defined in different ways. The first is defined as a named function test1(), while the other is defined as an anonymous function, which is assigned to the variable test2.

Now let’s have a look at what results we have in the Xcode console when I run this program with Ti 2.0.0 and my modified version of the TiJSCore library (click on the image to see it at full size with annotations):

What gets printed in the console log is the call graph of the program, recorded during its execution. Indentation reflects the caller->called hierarchy and the reported information includes (if available) the file containing the called function, the line where the function is defined the name of the function (more on this later) and the time statistics in terms of “Total Time” spent in the function and “Self Time”, which is given by the “Total Time” for the function minus the time spent in nested calls.

In the call graph, some calls are reported with <nofile> file information. These are mainly native and host functions (e.g. Math.cos(), Math.sin(), Ti.include(), and Ti.API.info()), for which no source file is given. Moreover, the calls reported to (program) are those happening in the global scope, while those reported as (Function object) are those made to native and host functions. Similarly, the calls reported as (anonymous function) are obviously those made to anonymous functions. So, depending on how a program is structured it may be more or less easy to interpret such profiling information. For instance, in my apps, a good 90% of the functions are anonymous.

How did I make it?

As I told, this is still work in progress and all I have profiled until now is some very basic test application like the one reported here. For achieving these early results I had to:

  1. Extend a bit the TiJSCore library, in order to expose a couple of functions to the Ti SDK, which are used for starting and stopping the profiler.
  2. Perform some very small modifications to the interpreter in order to enable code instrumentation (i.e. the code that’s used for generating profile data)
  3. Modify the iOS application template generated by the Ti SDK, in order to start the profiler when the first JS execution context is created, and stop the profiling when the application goes in background (e.g. because the user presses the home button), printing the profiling report as a result

All this isn’t usable yet for profiling “any” real world application, since most of the steps required still need to be done by hand (i.e. patching the Ti SDK and so on), so I think I’ll wait until the thing is a bit more stable before publishing the code.

Future steps

What’s missing? A lot of things, here are some:

  • Checking out what happens with event listeners and callbacks
  • Test with more complex applications
  • Creating install scripts in order to streamline the operation on existing applications
  • Move code for starting and stopping the profiling out of the Ti SDK and put it in a module
  • Enable the possiblity to start and stop the profiling and analyzing results from a front-end cli app

That’s it. If anyone is interested in more details don’t hesitate to contact me.

Building Titanium Mobile JSCore From Source

As I already mentioned here, the Titanium Mobile framework on iOS is based on JavaScriptCore (i.e. the engine used by WebKit) for interpreting and executing your app’s JS files.

Since part of my everyday work consists in hacking with the Ti SDK internals and building native modules it often happens that I need to track a bug or an issue down inside the core functions of the framework, and sometimes it would be useful to just take a look at the internal state of the JavaScript engine, in order to have a more detailed vision on where the problem at hand comes from.

However, the JSCore library (libTiCore.a) shipped with the Titanium SDK, is built in Release mode, with debug symbols stripped out, so, while its method and function names appear in a debug stack trace, it’s nearly impossible to look at actual variable and class member values.

Fortunately the source code of the library, customized by Appcelerator for integrating it with Titanium, is available on github, so we can create a custom build of it (e.g. a Debug version) and use it for our purposes.

Historically, building the library from scratch has not been much simple, nor documented. Moreover, since the process relied on several shell scripts, it was quite easy to get lost (at least at a first glance). However, in the last few months both Stephen Tramer and Blain Hamon (who are the main contributors to that code base) made a great work in simplifying and linearizing the build process.

This post aims at being just a quick tutorial for anyone needing to build libTiCore from scratch, so let’s dig in.

Building the libTiCore.a library

As usual, we can pull the git repo with:

git clone https://github.com/appcelerator/tijscore.git

Once downloaded, in the tijscore directory we’ll find a couple of scripts, namely fixup.py and buildit.sh and the TiCore directory, which contains the original files from the JSCore sources.

In order to build the library we first need to run:

./fixup.py

This script will patch most of the files in the TiCore directory, by changing names of files and symbols according to the Titanium namespace Ti, which is the one expected by the Ti SDK source code.

Then we can go with

./buildit.sh

This script will build the library and create a universal binary for the armv6, armv7 and i386 architectues. The build process is quite long (a bunch of minutes on my i7 MacBook Pro) and you’ll notice it’s completed when you hear the cooling fans of your computer stop whirling like crazy.

The buildit.sh script also accepts a CONFIG parameter that we can use for instructing it to build a debug version of the library:

./buildit.sh Debug

Once the build process is completed you’ll find the libTiCore.a¬†library binary in the TiCore/build directory. The last required step is to install it in the appropriate folder of the Ti SDK:

cp TiCore/build/libTiCore.a $TITANIUM_DIR/mobilesdk/osx/$TITANIUM_VERSION/iphone/

where $TITANIUM_DIR and $TITANIUM_VERSION are the root directory of your Ti SDK and the version you are currently using, e.g. /Library/Application\ Support/Titanium and 2.0.0 respectively.

A note on libTiCore.a versions vs Ti SDK versions

The Titanium Mobile SDK and the TiCore library are not really independent, so you must pay really big attention on which version of the library versus which version of the SDK you use, otherwise you will quite surely incur in linking errors when you build your titanium applications. For instance, this short tutorial is proved to work with version 16 (git hash ad8053020d) of the library, which is used by the version 2.0.0 of the Ti SDK.

For 1.8.X versions of the Ti SDK you should use version 15 of the library by checking out the git tag named TiCore-15 in the tijscore repository, e.g.:

git checkout TiCore-15

Simulating Slow Network Links on OSX

Testing mobile apps in the target platform simulator (either iOS or Android) can often be misleading, since the provided environment is an ideal one. The result is that an app working perfectly when executed in an emulated sandbox may expose unintended behaviors and perfomance when executed in open field on a real device. Moreover, not only physical resources, like processor performance and available memory are very different: also the characteristics of the network connection available to a development machine (i.e. wifi attached to a DSL or better link) usually outperform those of the mobile Internet links available in the wild, usually ranging from no connection at all to different kinds of 3G connections.

Several techniques do exist for simulating more realistic network characteristics when testing mobile apps on OS X, however most of them leverage the traffic shaping capabilities of the ipfw builtin firewall. In particular, they use the ipfw pipe command, which allows to define a pipe where all or part of the network traffic originating from, or directed to the host will be forced into.

The characteristics of the pipe can be shaped according to specific requirements in terms of bandwidth, delay and packet-loss-ratio of the link that needs to be modeled, thus enabling a high flexibility. A pipe can be configured through the following command:

ipfw pipe <num> config bw <bw> delay <d> plr <plr>

where num is a number identifying the pipe, bw the desired bandwidth measured in [K|M]{bit/s|Byte/s}, delay is the propagation delay measured in milliseconds, and plr is the packet-loss-ratio, i.e. a number in the range [0..1].

The following adds a firewall rule for the pipe:

ipfw add <rule-num> pipe <num> <protocol> from <src> to <dst>

The meaning of the command is the following:

* add rule with number rule-num
* get all the packets containing protocol and directed from src to dst
* flow them through the pipe identified by num

For example, modeling a GPRS link could be done with:

sudo ipfw pipe 1 config bw 56Kbit/s delay 200 plr 0.2
sudo ipfw add 1 pipe 1 ip from any to any

which forces all the ip traffic through a 56Kbps link with a 200ms delay, which loses 20 packets out of 100 in average.

It should be noted that while the rule is enforced, all the network traffic generated from or directed to the host machine is affected. Once the testing has been performed, the rule can be deleted with the command:

sudo ipfw delete 1

Not all network links have symmetric characteristics. In those cases it’s possible to model in a different way the uplink and the downlink sections with the following rules:

sudo ipfw pipe 1 config bw 780Kbps delay 100
sudo ipfw pipe 2 config bw 330Kbps delay 100
sudo ipfw add 1 pipe 1 in proto ip
sudo ipfw add 1 pipe 2 out proto ip

More details can be found in the ipfw man page and in the original Dummynet project page.

Using this technique from the command line, while effective, is probably not much practical. Moreover, figuring out realistic values for the required parameters can be a quite difficult task. A help in overcoming these issues comes from the developer tools available with XCode 4.2 on OS X Lion that, among others, provide a system preference pane called “Network Link Conditioner”, which allows to perform the same operations I listed before through a simple GUI, with a lot of predefined configuration templates.

The tool can be found here:

/Developer/Applications/Utilities/Network\ Link\ Conditioner/Network Link Conditioner.prefPane

and once installed is made available in the System Preferences:

The panel allows selecting a configuration from a list of presets, which comprise different kinds of mobile and “home” network links:

The desired settings can be activated through the big switch present on the left of the panel and, in case the available presets are not sufficient, it’s possible to define custom configurations through the “Manage Profiles” button: