views:

159

answers:

1

I'm looking for advice to speed up serialization performance, specifically when using the Google Android. For a project I am working on, I am trying to relay a couple hundred objects from a server to the Android app, and am going through various stages to get the performance I need.

First I tried a terrible XML parser that I hacked together using Scanner specifically for this project, and that caused unbelievably slow performance when loading the objects (~5 minutes for a 300KB file). I then moved away from that and made my classes implement Serializable and wrote the ArrayList of objects I had to a file. Reading that file into the objects the Android, with the file already downloaded mind you, was taking ~15-30 seconds for the ~100KB serialized file. I still find this completely unacceptable for an Android app, as my app requires loading the data when starting the application.

I have read briefly about Externalizable and how it can increase performance, but I am not sure as to how one implements it with nested classes. Right now, I am trying to store an ArrayList of the following class, with the nested classes below it.

public class MealMenu implements Serializable{
private String commonsName;
private long startMillis, endMillis, modMillis;
private ArrayList<Venue> venues;
private String mealName;
}

And the Venue class:

public class Venue implements Serializable{
private String name;
private ArrayList<FoodItem> foodItems;
}

And the FoodItem class:

public class FoodItem implements Serializable{
private String name;
private boolean vegan;
private boolean vegetarian;
}

IF Externalizable is the way to go to increase performance, is there any information as to how java calls the methods in the objects when you try to write it out? I am not sure if I need to implement it in the parent class, nor how I would go about serializing the nested objects within each object.

+1  A: 

Never use Serializable across architectures. You have no way of knowing if the Dalvik VM will have compatible serialization to your server's Java version. Even if it works today, it might not with upgrades on either end. Always choose something that is designed specifically to work across architectures.

Options include:

  • Protocol Buffers
  • Apache Thrift (the payload packaging, not necessarily the RPC stuff)
  • XML (you neglected to mention what parser you used -- if you used DOM, try SAX)
  • JSON (reportedly the Jackson JSON parser is faster than the org.json parser built into Android)

Also, loading 300K of data on app startup is a prescription for trouble. Please consider leveraging SQLite to allow you to work with just the bits of data you need at a time.

CommonsWare
Not sure I understand that comment -- with `Serializable` you don't have to rely on the default mechanism. You can always define your own with `readFields()` et al.
Sean Owen
And you assume those fields are consistently encoded across architectures. Serialization is designed for storage for an individual machine, not across machines, let alone across chipsets and VM authors.
CommonsWare
I switched over to an SQLite database as you suggested, and the load times for the application are drastically better. However, populating the database is still taking a huge amount of time. With the current database design were adding ~3000 rows when we populate the database, as well as when adding new content. ~2500 to one table, ~500 to another, and ~150 to a third.Is there anything we could be doing wrong in this regard? It was taking probably at least a minute to add the rows to the database. The only thing that comes to my mind is redesigning our database usage so we don't need so many
Jomanscool2
@Jomanscool2 "Is there anything we could be doing wrong in this regard?" Be sure to use transactions, rather than just the default of one-transaction-per-insert. Clustering, say, 100 inserts to a transaction should help some. For data you are shipping with the app, you could ship an actual SQLite database and unpack it on the phone, trading off space for speed. Or, you could download a pre-populated SQLite database. All that being said, writing to flash is slow and highly variable.
CommonsWare
Thank you for your fast response. We had looked into just shipping an SQLite database and may look into that more, but I think we will first try to 'cluster to transactions'. Regardless, thank you very much for your very valuable information. It has helped us get to where we are today.
Jomanscool2