SwiftKickMobile / TLIndexPathTools

TLIndexPathTools is a small set of classes that can greatly simplify your table and collection views.
tlindexpathtools.com
MIT License
347 stars 60 forks source link

loading time #42

Closed ghazel closed 9 years ago

ghazel commented 9 years ago

With a data set of 10k items, the TLIndexPathDataModel takes 45 seconds to load. With 5k items, it takes 11 seconds. With 1k items it loads in under a second.

What is it doing which is so non-linear?

wtmoose commented 9 years ago

I’ve had problems with UICollectionView’s internal batch update process getting extremely slow with large updates. If you're using UICollectionView, I would suggest profiling it.

I don't completely understand what you mean by "loading". Can you describe what components of TLIPT you're using, e.g. TLCollectionViewController, TLIndexPathController, etc. and how you're creating and updating your data model?

ghazel commented 9 years ago

Yes, perfomBatchUpdates is hidiously slow with >100 items.

By loading I mean; setting items, which builds all the lookup tables. Easy to see in the Shuffle/Filter demo by making an array of 5k items (make sure they are unique).

wtmoose commented 9 years ago

I was able to get the Shuffle demo with 5000 items in Simulator down to 2.5s from 15s. The remaining 2.5s was made up of:

  1. 2.0s in [UICollectionView _endItemAnimations] mainly manipulating index paths. There is nothing I can do about this.
  2. 0.5s in AutoReleasePoolPage::pop(void*). A lot of this is likely due to temporary objects created in TLIndexPathUpdates, but I don't know how much this can be improved and it could be a significant undertaking that I don't have time for.

The issue is summarized as follows. Ultimately, the problem was that the data model items were arrays:

NSArray *items = @[
       @[@"A", [UIColor colorWithHexRGB:0x443695]],
       @[@"B", [UIColor colorWithHexRGB:0x00B1D7]],
       @[@"C", [UIColor colorWithHexRGB:0xF42994]],
       @[@"D", [UIColor colorWithHexRGB:0x0A0916]],
       @[@"E", [UIColor colorWithHexRGB:0xF4E353]],
       @[@"F", [UIColor colorWithHexRGB:0x537B28]],
       ];

TLIPT was calling isEqual on these arrays a lot and this was really slow. The fix involves two changes. The first change was a performance optimization I made in TLIPT to eliminate a bunch of isEqual calls. You'll need to update to version 0.3.8. The second change, which is something you'll probably need to do in our code, was to provide an explicit identifier for each data model item. isEqual gets called on the identifier instead of the item and, with an appropriate choice of identifier, this is much, much faster.

Item identifiers are discussed in the TLIndexPathDataModel API documentation in the "Item Identification" section. The short story is that, in some cases such as the Shuffle example, the item itself is used as the identifier. And if the item's isEqual method is expensive, the data model will not scale. The way to fix this is to provide an explicit unique identifier with a fast isEqual method, such as an NSString. The various TLIndexPathDataModel initializers provide a few options for specifying identifiers. In the Shuffle example, I used the block-based initializer and the first element of the array, i.e. the unique string, as the identifier:

self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:items sectionNameBlock:nil identifierBlock:^id(id item) {
    return item[0];
}];

Thats about it. Please let me know if this helps your project.

wtmoose commented 9 years ago

No reply. Closing.