While application performance is always in the back of your mind when developing PC applications it becomes much more important when developing on a mobile platform. The hardware is slower and the user expectations are much higher.

This problem came to the fore for me recently as I was porting UPM to the Android platform. Since UPM is a Java application I was able to reuse quite a bit of the code with little or no modification (all bar the SWING code actually).

During the porting process I found that opening the password database on the Android Emulator took about 12 seconds. This was a sub-second operation on the PC version so there was obviously a problem. Using Traceview, the profiling tool that comes with the Android SDK, the problem soon became apparent.

UPM stores all it’s data in an encrypted file. This file is read into memory where it’s decrypted. Here’s the code that was reading in the file…

FileInputStream fis = new FileInputStream(databaseFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = 0;
while ((i = fis.read()) != -1) {
    baos.write(i);
}
byte[] fullDatabase = baos.toByteArray();
baos.close();
fis.close();

Looking at it now it’s obviously bad code from a performance point of view as it’s reading in the file byte by byte. The reason I never replaced it was that it simply wasn’t a problem when running on a PC. The database file it reads is only a few kilobytes in size so it ran in under a second.

After identifying the bad code I replaced it with the following which runs in under a second.

InputStream is = new FileInputStream(file);

// Get the size of the file
long length = file.length();

// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];

// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
    offset += numRead;
}

// Ensure all the bytes have been read in
if (offset < bytes.length) {
    throw new IOException("Could not completely read file " + file.getName());
}

is.close();

The lesson here is that Android, and mobile platforms in general, require you think a little bit more about elements of your design and code than you might normally.

Some useful Android links:

Designing for Performance

Designing for Responsiveness