2

NSFetchedResultsController is set to 5 for fetch batch size. We notice it's slow loading, so we enable SQLDebug. For some reason, it's loading 5 rows at a time, but it's doing this for all 100 rows on initial load. Once it's loaded, it seems to load 5 rows at a time.

When watching the console, I see the query ran 20 times; there are a total of 100 rows. I would have expected this to run 1 time with the first 5 rows and as you scroll, more rows would be loaded. I also tried changing the fetch size and it has the same behavior.

The setup of the fetched results controller is below.

- (NSFetchedResultsController*) fetchedResultsController {

    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    [NSFetchedResultsController deleteCacheWithName:@"Root"];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription 
                                   entityForName:@"Message" inManagedObjectContext:_context];

    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"conversation = %@", conversation];

    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] 
                              initWithKey:@"timestamp" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:5];

    NSFetchedResultsController *theFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                        managedObjectContext:_context sectionNameKeyPath:nil 
                                                   cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    [sort release];
    [fetchRequest release];
    [theFetchedResultsController release];

    return _fetchedResultsController;    

}
tjg184
  • 4,508
  • 1
  • 27
  • 54

1 Answers1

6

We use NSFetchedResultsController in conjunction with a tableview. The tableview will ask the NSFetchedResultsController for as many rows as it needs to fill up the rows it thinks it will need to show and keep on hand for performance reasons. By keeping the batch size artificially low, you are causing the NSFetchedResultsController to make more round trips back to the store.

Set it to 100 or so and see what your performance is like. If you are having performance issue with a batch size of 100, you may have to normalize your core data model. Check out the WWDC videos on Core Data from 2010. It has a great video on optimizing core data and the fetches associated with NSFetchedResultsController.

Good luck

timthetoolman
  • 4,613
  • 1
  • 22
  • 22