Search code examples
iphoneperformancetestingios5instruments

My app is suffering from major performance issues with iOS 5, can someone help me make sense of this speed test log from instruments?


I have a simple reading app that uses fmdb to talk to the database and then fill up a UIWebview with text. Since the glorious advent of ios 5 it runs very poorly...

When I am change chapters in my book via a segmentedControl tap. In ios 4.3, it was SUPER fast. Now, as you can see below, it isn't:

enter image description here

So obviously things are loading slow, but I don't know how to read the results of the speed test. Which method is the main culprit? What do I need to do to optimize the app? Is there anything else I can do to understand where exactly the hang-ups are?

I am having such a hard time with fmdb and ios 5 that I am considering other options. Should I just scrap fmdb? And go for the direct ios sqlite db approach?

I am finding the instruments tool to be useful, but very hard to understand and use.

UPDATE

Here is the change chapter method:

- (IBAction) changeChapter:(id)sender {
if ([prevNext selectedSegmentIndex] == 0) {
    //previous
    [self setCurrentChapter:(currentChapter-1)];
} else {
    //next
    [self setCurrentChapter:(currentChapter+1)];
}
[self refreshUI];
}

UPDATE 2:

Here is the code that instruments is telling me is the problem. It is the next method that fmdb uses to iterate through the FMResultSet:

- (BOOL) next {

int rc;
BOOL retry;
int numberOfRetries = 0;
do {
    retry = NO;

    rc = sqlite3_step(statement.statement); //Instruments says this is 100% the problem

    if (SQLITE_BUSY == rc) {
        // this will happen if the db is locked, like if we are doing an update or insert.
        // in that case, retry the step... and maybe wait just 10 milliseconds.
        retry = YES;
        usleep(20);

        if ([parentDB busyRetryTimeout] && (numberOfRetries++ > [parentDB busyRetryTimeout])) {

            NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]);
            NSLog(@"Database busy");
            break;
        }
    }
    else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
        // all is well, let's return.
    }
    else if (SQLITE_ERROR == rc) {
        NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
        break;
    } 
    else if (SQLITE_MISUSE == rc) {
        // uh oh.
        NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
        break;
    }
    else {
        // wtf?
        NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
        break;
    }

} while (retry);


if (rc != SQLITE_ROW) {
    [self close];
}

return (rc == SQLITE_ROW);
}

FMDB is all I've ever known as far as sqlite goes, is it even worth it? Should I just scrap it and move to the cocoa-touch sqlite api's?


Solution

  • Ok I was actually able to get this information from someone on the FMDB mailing list. He suggested that I add an index to my db tables that were being called frequently, and that fixed it!

    Apparently Apple changed the version of sqlite in iOS 5.

    From the FMDB post:

    Creating an index in sqlite is easy - see sqlite.org for the syntax. The trick is figuring out what index(es) to create. In my case I had a query like: select a,b,c from x where sid=somevalue; sid was not the primary key for the table so there wasn't an index on it. Adding an index on sid made that query much faster since the index allows it to quickly find tuples. Note that indexes can slow down updates, inserts, and deletes on the table so don't just randomly add indexes to your tables. Look at your queries and see what columns are used in the where clause of your queries.