From 61c1524bb0c59d5eb43f65b02442ad50dfb2d0dc Mon Sep 17 00:00:00 2001 From: Ryan Nystrom Date: Wed, 12 Jul 2017 12:40:18 -0700 Subject: [PATCH] Add experiment for reloadData on large changesets Summary: Preparing another perf test. I noticed in some surfaces that have **massive** updates (8k+ inserts/deletes) that perf can be pretty awful. This is all due to internals of `UICollectionView` trying to create cells and animate a huge blob of changes. Instead, I'm picking a sensible (is it?) default to just skip batch updates and do `reloadData` instead. Unit tests caught that the `layoutIfNeeded` is required to immediately configure cells. Depends on D5392713 Reviewed By: jeremycohen Differential Revision: D5392882 fbshipit-source-id: e429ddb7bca7400908898ebc6f097a489211b03d --- Source/IGListAdapterUpdater.m | 20 ++++++++++++++------ Tests/IGListAdapterE2ETests.m | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Source/IGListAdapterUpdater.m b/Source/IGListAdapterUpdater.m index 75229b8b..66d68831 100644 --- a/Source/IGListAdapterUpdater.m +++ b/Source/IGListAdapterUpdater.m @@ -15,6 +15,7 @@ #import #import "UICollectionView+IGListBatchUpdateData.h" +#import "IGListIndexSetResultInternal.h" #import "IGListMoveIndexPathInternal.h" #import "IGListReloadIndexPath.h" @@ -167,16 +168,21 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray= NSFoundationVersionNumber_iOS_8_3); if (iOS83OrLater && self.allowsBackgroundReloading && collectionView.window == nil) { [self beginPerformBatchUpdatesToObjects:toObjects]; - executeUpdateBlocks(); - [self cleanStateAfterUpdates]; - [self performBatchUpdatesItemBlockApplied]; - [collectionView reloadData]; - executeCompletionBlocks(YES); + reloadDataFallback(); return; } @@ -217,7 +223,9 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray 100 && IGListExperimentEnabled(experiments, IGListExperimentReloadDataFallback)) { + reloadDataFallback(); + } else if (animated) { [collectionView performBatchUpdates:^{ batchUpdatesBlock(result); } completion:batchUpdatesCompletionBlock]; diff --git a/Tests/IGListAdapterE2ETests.m b/Tests/IGListAdapterE2ETests.m index 9dcf810c..79856ed1 100644 --- a/Tests/IGListAdapterE2ETests.m +++ b/Tests/IGListAdapterE2ETests.m @@ -1521,4 +1521,25 @@ [self waitForExpectationsWithTimeout:30 handler:nil]; } +- (void)test_whenMassiveUpdate_thatUpdateApplied { + // init empty + [self setupWithObjects:@[]]; + + ((IGListAdapterUpdater *)self.updater).experiments = IGListExperimentReloadDataFallback; + + NSMutableArray *objects = [NSMutableArray new]; + for (NSInteger i = 0; i < 3000; i++) { + [objects addObject:genTestObject(@(i + 1), @4)]; + } + self.dataSource.objects = objects; + + XCTestExpectation *expectation = genExpectation; + [self.adapter performUpdatesAnimated:YES completion:^(BOOL finished) { + XCTAssertEqual([self.collectionView numberOfSections], 3000); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + @end