Sunday, May 23, 2010

Android: Serializable Considered Harmful

This is an old problem, but anyone I can convince not to use Serializable on Android will help the system as a whole.

There is some data saved between launches of my application - a list of complex objects. When I first learned Android I assumed that the fastest way to get the app up and running would be to slap Serializable on my data classes and call it a day. It certainly got things up and running quickly, but with some serious performance issues. I never noticed this in early testing because I only saved a few objects at a time. However, when I got up to 5+ objects the system started to slow down, and at 10+ it ran like molasses. There's not normally that many objects, but it's still something to be concerned about. It's not like I was doing anything complex, however - it was simply that Serializable is that slow.

Not only that, but I had to live in constant fear of changing the data structure. If enough things changed I would have to write my own serialization processes to work with backwards compatibility. Yuck.

I switched to using JSON to store all my data and this decision has made my life so much better. Android comes with a good JSON library and it's pretty simple to add JSON support to classes. JSON is much, much faster than serialization and comes out with much smaller results, too (you can even GZip the results to make them smaller still). To put it in perspective, the save time is now unnoticeable, whereas I could count the seconds using Serializable; and the file size was reduced by an order of magnitude.

Not only is it better for saving data, it's a very easy way to pass data between components. When I first started, I saw three ways to pass data between components: Serializing, parceling, or storing data in the Application context. Serializing was proving too slow, parceling is really a pain in the ass, and the last solution is harder to integrate with later on (no one else can call your component). JSON has proven a much better solution - it's fast enough to get by, but not nearly the pain in the ass that Parcels are.

9 comments:

  1. Simple, easy understand and all I needed.

    Thank you,

    ReplyDelete
  2. I'm a seasoned coder, but a beginner Android developer.. I had stumbled across Serializable and thought I'd found my storage solution, but I too noticed slow performance when saving multiple Objects. I had no idea I could use JSON, but a Google search for Serializable help brought me here.. Thanks!

    ReplyDelete
  3. Thanks for the heads up! Like many platforms, nuts and bolts reference material (e.g. API docs, source) are in abundance, but higher-level wisdom about best practices and lessons learned are in short supply. It's great to find tips like this.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. When you suggest replacing serialization with JSON are you referring to writing text files to the disk containing JSON representations of the objects you used to serialize?

    ReplyDelete
  6. @Andrew: Yes, that is an option that I use pretty often. It's a good trade off between ease of portability and speed. It will not fit everyone's needs but it is undoubtably better than serialization.

    ReplyDelete
  7. This is terrible advice: "anyone I can convince not to use Serializable on Android will help the system as a whole". Why should someone use Serializable? Supposed I have a small class I need to pass with an intent or some information I need to save when an activity is stopped and restarted. The BEST solution is Serializable. Why? It's simple and simple works well. Why is your advice so bad? You are using an absolute. Yes, Serializable is incredibly slow on Android. And, I'm reading everywhere that you should never, never use it because it is so slow. Why, I'll bet is takes darned near a millisecond to serialize most of the cases where I use it. Incredibly slow...

    What should you do: Implement Serializable. If, as in your application, it is too slow, do something else. Obviously, if you know you have a large amount of data, you know Serializable won't work. But, the idea that someone would go through all of the trouble to convert a class with 10 member variables into JSON just to pass it around in an application is ludicrous to me.

    ReplyDelete
    Replies
    1. Wow, that's lot of anger over a minor disagreement. I love the internet, where one can get so worked up where a simple conversation would suffice in person. :)

      I can't argue with a very simplistic use of Serializable. At the time I was writing this in the context of larger objects. For a small amount of data it could be alright, given the context (1ms can mean the world if you're mid-animation). Personally, I'd rather just not worry about the problem at all by not using slow implementations; it's not like JSON is much more work if you're only dealing with a few fields.

      Also, since I was focused on large datasets, I missed a fourth option for passing data: just add primitives/Strings to the Bundle itself (for Intent data or saving instance state). If you've only got a few things to pass, I much prefer this method, since it lets you skip creating an interim Object altogether.

      Delete
  8. A compromise would be to writeReplace to and readResolve from a String with the JSON representation, but only in objects that are leaves modulo String.

    ReplyDelete