Wikimedia Apps/Android/Memory usage

The following are some recommendations for improving app memory usage and performance, based on my profiling of our app.

(in rough order of priority!)

Page cache
At the moment, we cache the last 10 visited articles in memory (in the Java VM heap). This is probably a bad idea, since the size of each article is not predictable, and the VM size varies greatly across different devices and Android versions (it's as small as 24MB on older devices).

One straightforward solution to this would be to cache the pages by writing them to local storage. We could probably reuse our logic for Saved Pages, and automatically "save" the page as soon as it's loaded. That way, it will be cached by default, and if the user actually wants to save the page, all we have to do is add the entry to the saved-pages sqlite table. If I'm not mistaken, this is already how it's done in the iOS app (?).

Another possible option (a very naughty one) is to use native code to allocate and store cached articles. Since these allocations would be made in the native heap instead of the Java heap, we would have access to an order of magnitude more memory. [brb need to wash hands after writing that sentence]

Page backstack
At the moment, when the user navigates to a new article, the previous fragment is placed onto the backstack of the activity. Even though the fragment object is relatively light, if the user visits enough articles, the backstack may still eventually grow beyond the memory limit of the app, causing it to crash.

The solution to this would be... to reuse a single WebView (and thus a single fragment) for loading any number of articles. I've experimented with this in the recent past, and I recall having some problems on 2.3 devices, but it may be time to revisit that patch, and iron out the issues.

Reusing the same WebView would provide additional benefits, including reduced initialization and GC cost, which will translate into better performance.


 * It may also be possible to do a less dramatic change, such as closing out the WebView when placing something on the back stack and reloading the page from cache when reshowing the fragment. This would still have GC churn but might be easier to implement. --brion

Javascript bridge
We do some pretty heavy transactions across our "bridge" between Java and the WebView (i.e. when loading page sections). We may want to think about switching to filesystem-based section loading: after fetching a section from the network, write it to a file, and then trigger the WebView to load the section from the file.

Picasso cache
The Picasso library (which we use to load images from the network) automatically caches the images in local storage. This is generally a nice feature, but it seems to cache the images without any bounds. We should investigate the possibility of hooking into Picasso's caching logic, and trim the cache when it exceeds a certain limit.