From a09242e2791a47769fb70fc31f5e18f0ea0b07ee Mon Sep 17 00:00:00 2001 From: Tim Johnsen Date: Thu, 3 Jan 2019 09:24:23 -0800 Subject: [PATCH] Add experiment to perform IGListAdapterUpdater background updates on a serial queue. Summary: This diff adds a new `IGListExperimentBackgroundDiffingSerial` experiment that behaves similarly to `IGListExperimentBackgroundDiffing` but executes changes in a per-`IGListAdapterUpdater` serial queue instead of a global queue. Global queues are concurrent, and concurrent queues by nature don't ensure the execution order of the blocks that are enqueued into them, so there's a chance that the former `IGListExperimentBackgroundDiffing` experiment would lead to changes being applied out of order. Reviewed By: calimarkus Differential Revision: D13567403 fbshipit-source-id: a2aebb20e5e7dc22601fad3c2dfc80112747c81b --- Source/Common/IGListExperiments.h | 2 ++ Source/IGListAdapterUpdater.m | 12 ++++++++++-- Source/Internal/IGListAdapterUpdaterInternal.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Common/IGListExperiments.h b/Source/Common/IGListExperiments.h index 30048f33..0f243327 100644 --- a/Source/Common/IGListExperiments.h +++ b/Source/Common/IGListExperiments.h @@ -26,6 +26,8 @@ typedef NS_OPTIONS (NSInteger, IGListExperiment) { IGListExperimentGetCollectionViewAtUpdate = 1 << 7, /// Test skipping layout when UICollectionView isn't visible IGListExperimentSkipLayout = 1 << 8, + /// Test updater diffing performed on a serial background queue. + IGListExperimentBackgroundDiffingSerial = 1 << 9, }; /** diff --git a/Source/IGListAdapterUpdater.m b/Source/IGListAdapterUpdater.m index 778c0c5c..859c5993 100644 --- a/Source/IGListAdapterUpdater.m +++ b/Source/IGListAdapterUpdater.m @@ -267,9 +267,17 @@ willPerformBatchUpdatesWithCollectionView:collectionView } }; - // temporary test to try out background diffing + dispatch_queue_t asyncQueue = nil; if (IGListExperimentEnabled(experiments, IGListExperimentBackgroundDiffing)) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + asyncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + } else if (IGListExperimentEnabled(experiments, IGListExperimentBackgroundDiffingSerial)) { + if (_backgroundUpdateQueue == nil) { + _backgroundUpdateQueue = dispatch_queue_create("io.github.instagram.IGListKit.backgroundupdatequeue", DISPATCH_QUEUE_SERIAL); + } + asyncQueue = _backgroundUpdateQueue; + } + if (asyncQueue) { + dispatch_async(asyncQueue, ^{ IGListIndexSetResult *result = performDiff(); dispatch_async(dispatch_get_main_queue(), ^{ performUpdate(result); diff --git a/Source/Internal/IGListAdapterUpdaterInternal.h b/Source/Internal/IGListAdapterUpdaterInternal.h index b794608b..40c8ef52 100644 --- a/Source/Internal/IGListAdapterUpdaterInternal.h +++ b/Source/Internal/IGListAdapterUpdaterInternal.h @@ -41,6 +41,8 @@ FOUNDATION_EXTERN void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, @property (nonatomic, assign) IGListBatchUpdateState state; @property (nonatomic, strong, nullable) IGListBatchUpdateData *applyingUpdateData; +@property (nonatomic, strong) dispatch_queue_t backgroundUpdateQueue; + - (void)performReloadDataWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock; - (void)performBatchUpdatesWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock; - (void)cleanStateBeforeUpdates;