What do you do when your PhoneGap app is running slow, and you don’t know why?
It’s a problem that faces every mobile developer—your application has slowed down and is eventually brought to its knees.
But why? You’ve kept in mind all of the basic principles in creating a better PhoneGap app, but you’re still not getting the user experience you want. You think to yourself that your application is not that complicated. Inevitably if games like Infinity Blade III can run as smoothly as butter, then there’s no reason your simple sliding animation can’t run.
So what do you do? Poke and prodding and guessing and checking? Maybe.
But before you start with that, let’s get out some of our tools and measure our application.
Measuring is an important principle—it’s one I’ll be covering in my upcoming talk at DevLearn about Developing Better PhoneGap Applications.
A considerable part of building a successful application is measuring where you’re at. This seems evident for usage analytics, but it’s just as important when focusing on the user experience.
There are tools available to us to assist in measuring our application and highlighting problems.
Measuring CPU Usage
The time the CPU spends tending to your application is the time it cannot spend listening to the user.
As of Xcode 5, Apple has provided a useful set of debugging tools that give us an overview of the current usage of system resources, including CPU usage. Since these are available anytime you debug on the device, it would be a good practice to get into the habit of monitoring these meters each time you debug on the device (which should frequently be).
These are high-level overviews of what’s going on. They are intended to give quick indications of new problems that may have risen during development. Let’s say after implementing a new feature; you notice a pattern like:
Over time, the CPU usage of the application continues to rise and remains consumed even when the app should just be waiting for user interaction. This alone doesn’t tell us anything beyond that the CPU is busy when we expected it to be idle. Offhand, we know that a burdened CPU could result from a few things:
Perhaps the rendering engine must do a lot of calculation and layout work (“reflow”) or painting when it need not be.
Using Safari’s Remote Web Inspector
Safari has a remote Web inspector that can attach to a WebKit process running on a connected iOS device and give us valuable insight into what’s going on beneath the hood. This requires a little bit of setup get started.
Note: If your device isn’t appearing in the Develop menu, try quitting and relaunching Safari.
Typically, see a pattern that follows something like this:
As the user interacts with your application (events are shown in yellow), it will likely require the interface to respond in some way, triggering new layout and rendering events (shown in purple). The table below the timeline shows what layout work is being down by the browser. The large white spaces show the time that the Web view sat idle waiting for user interaction.
But let’s say you see a pattern that resembles something like this:
After some user interaction, your application continues to do a lot of layouts and rendering work, even 10 seconds after the user has finished interacting with the app.
Depending on your application, it may expect this (perhaps it’s running through an animation sequence).
Maybe it comes as a surprise to you. If you’re in a state in your application where you expect it to be sitting idle and you see a pattern like this, then you know something is up. Perhaps you already have an idea what’s going on. In which case, great! Now you’ve isolated the issue to unneeded layout and rendering work and can make changes in your code, all the while remeasuring to test your hypothesis.
You might still be unsure as to exactly what a section of code is misbehaving. So let’s cover one last tool.
However, you still can get useful information running the app in Safari on your computer (think of your computer as the “best-case scenario”—if a problem shows up there, then it will show up on the device).
You should focus on just one problem at a time. Run actions that lead up to the problem.
You’ll want to start by focusing on the items with the highest amount of time, and especially be keeping an eye out for your code to show up.
If you’re using a JS library (like jQuery or Zepto), you’ll likely see it appear many times, and often near the top. This is not (necessarily) because it’s running slowly, but because your code is probably making several calls to that library. Focus on your code for now.
The “Self” column shows the time spent within the function. The total time shows the time spent testing the entire purpose, including calls it made to other features.
As you dig down, you may find lines of your code that are taking up a lot of total time—functions that perhaps you did not expect to be so time-consuming.
And here is where we debug our application. What changes if we skip calls to this function entirely? What specific pieces of this function are taking the most time, and how can we mitigate that?
You can even set breakpoints to stop execution within a function to get an in-depth view of the execution path at that point. These breakpoints also work during remote debugging on the actual device.
Bringing it All Together
In all of this, we’re striving for the best user experience possible. The work we’re doing here does not differ from the development and debugging process of a native application (and why should it be?). What the goal is measuring is to save time spent guessing and checking so we can more precisely pinpoint problems when they exist.
Again, measuring is only one of many essential steps in developing a better PhoneGap application.
If you’re interested in getting an overview of the others, be sure to check out my session at DevLearn, Friday at 8:30 a.m. Hope to see you there!
Latest posts by Daniel Pfeiffer (see all)
- A More Mobile-Friendly Captivate HTML Template - October 21, 2013
- 3 Tools To Help You Optimize Your PhoneGap App’s Performance - October 15, 2013
- Tin Can iOS Library Compatible With Version 1.0 - May 2, 2013