R – What’s the fastest way to save data and read it next time in a IPhone App

iphoneoptimizationperformanceserialization

In my dictionary IPhone app I need to save an array of strings which actually contains about 125.000 distinct words; this transforms in aprox. 3.2Mb of data.

The first time I run the app I get this data from an SQLite db. As it takes ages for this query to run, I need to save the data somehow, to read it faster each time the app launches.

Until now I've tried serializing the array and write it to a file, and afterword I've tested if writing directly to NSUserDefaults to see if there's any speed gain but there's none. In both ways it takes about 7 seconds on the device to load the data. It seems that not reading from the file (or NSUserDefaults) actually takes all that time, but the deserialization does:

objectsForCharacters = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain];

Do you have any ideeas about how I could write this data structure somehow that I could read/put in memory it faster?

Best Solution

The UITableView is not really designed to handle 10s of thousands of records. If would take a long time for a user to find what they want.

It would be better to load a portion of the table, perhaps a few hundred rows, as the user enters data so that it appears they have all the records available to them (Perhaps providing a label which shows the number of records that they have got left in there filtered view.)

The SQLite db should be perfect for this job. Add an index to the words table and then select a limited number of rows from it to show the user some progress. Adding an index makes a big difference to the performance of the even this simple table.

For example, I created two tables in a sqlite db and populated them with around 80,000 words

#Create and populate the indexed table
create table words(word);    
.import dictionary.txt words
create unique index on words_index on word DESC;

#Create and populate the unindexed table
create table unindexed_words(word);
.import dictionary.txt unindexed_words

Then I ran the following query and got the CPU Time taken for each query

.timer ON
select * from words where word like 'sn%' limit 5000;
...
>CPU Time: user 0.031250 sys 0.015625;

select * from unindex_words where word like 'sn%' limit 5000;
...
>CPU Time: user 0.062500 sys 0.0312

The results vary but the indexed version was consistently faster that the unindexed one.

With fast access to parts of the dictionary through an indexed table, you can bind the UITableView to the database using NSFecthedResultsController. This class takes care of fecthing records as required, caches results to improve performance and allows predicates to be easily specified.

An example of how to use the NSFetchedResultsController is included in the iPhone Developers Cookbook. See main.m