Skip to content

Commit

Permalink
lower diffing priority if the collection-view is not visible
Browse files Browse the repository at this point in the history
Summary: Lower QOS to give on-screen work priority.

Differential Revision: D60691856

fbshipit-source-id: 52b10e05cb999214ca6c6a8fe1cb3ce2dd847eb1
  • Loading branch information
Maxime Ollivier authored and facebook-github-bot committed Aug 6, 2024
1 parent 59365a1 commit f429ec5
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Source/IGListDiffKit/IGListExperiments.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ typedef struct IGListAdaptiveDiffingExperimentConfig {
BOOL higherQOSEnabled;
/// If both item counts are under this number, we'll run the diffing on the main thread.
NSInteger maxItemCountToRunOnMain;
/// Lower QOS if view is not visible according to `IGListViewVisibilityTracker`
BOOL lowerPriorityWhenViewNotVisible;
} IGListAdaptiveDiffingExperimentConfig;

/**
Expand Down
1 change: 1 addition & 0 deletions Source/IGListKit/Internal/IGListBatchUpdateTransaction.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ - (void)_diff {

__weak __typeof__(self) weakSelf = self;
IGListPerformDiffWithData(data,
self.collectionView,
self.config.allowsBackgroundDiffing,
self.config.adaptiveDiffingExperimentConfig,
^(IGListIndexSetResult * _Nonnull result, BOOL onBackground) {
Expand Down
4 changes: 3 additions & 1 deletion Source/IGListKit/Internal/IGListPerformDiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ typedef void (^IGListDiffExecutorCompletion)(IGListIndexSetResult *result, BOOL
Perform diffing, which can happen sync or async depending on the params given.
@param data Contains the objects before and after the update
@param view View on which we will perform the update. Used to check visibility.
@param allowsBackgroundDiffing Allows the diffing to be performed off the main thread
@param adaptiveConfig Details of how the adaptive diffing should work
@param completion Returns the diffing results. Can be called async or sync, but will be called on main thread.
*/
NS_SWIFT_NAME(ListPerformDiff(data:allowsBackgroundDiffing:adaptiveConfig:completion:))
NS_SWIFT_NAME(ListPerformDiff(data:view:allowsBackgroundDiffing:adaptiveConfig:completion:))
FOUNDATION_EXTERN void IGListPerformDiffWithData(IGListTransitionData *_Nullable data,
UIView *_Nullable view,
BOOL allowsBackgroundDiffing,
IGListAdaptiveDiffingExperimentConfig adaptiveConfig,
IGListDiffExecutorCompletion completion);
Expand Down
19 changes: 16 additions & 3 deletions Source/IGListKit/Internal/IGListPerformDiff.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#endif

#import "IGListTransitionData.h"
#import "IGListViewVisibilityTracker.h"

#pragma mark - Regular (not adaptive)

Expand All @@ -35,11 +36,21 @@ static void _regularPerformDiffWithData(IGListTransitionData *_Nullable data,

#pragma mark - Adaptive

static dispatch_queue_t _queueForData(IGListTransitionData *data, BOOL allowsBackground, IGListAdaptiveDiffingExperimentConfig adaptiveConfig) {
static dispatch_queue_t _queueForData(IGListTransitionData *data,
UIView *view,
BOOL allowsBackground,
IGListAdaptiveDiffingExperimentConfig adaptiveConfig) {
if (!allowsBackground) {
return dispatch_get_main_queue();
}

if (adaptiveConfig.lowerPriorityWhenViewNotVisible) {
IGListViewVisibilityTracker *const tracker = IGListViewVisibilityTrackerAttachedOnView(view);
if (tracker && tracker.state == IGListViewVisibilityStateNotVisible) {
return dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);
}
}

// If we don't have a lot of items, the dispatching back and forth can add unnecessary delay.
if (data.fromObjects.count < adaptiveConfig.maxItemCountToRunOnMain
&& data.toObjects.count < adaptiveConfig.maxItemCountToRunOnMain) {
Expand All @@ -51,10 +62,11 @@ static dispatch_queue_t _queueForData(IGListTransitionData *data, BOOL allowsBac
}

static void _adaptivePerformDiffWithData(IGListTransitionData *_Nullable data,
UIView *view,
BOOL allowsBackground,
IGListAdaptiveDiffingExperimentConfig adaptiveConfig,
IGListDiffExecutorCompletion completion) {
const dispatch_queue_t queue = _queueForData(data, allowsBackground, adaptiveConfig);
const dispatch_queue_t queue = _queueForData(data, view, allowsBackground, adaptiveConfig);

if (queue == dispatch_get_main_queue() && [NSThread isMainThread]) {
IGListIndexSetResult *const result = IGListDiff(data.fromObjects, data.toObjects, IGListDiffEquality);
Expand All @@ -72,6 +84,7 @@ static void _adaptivePerformDiffWithData(IGListTransitionData *_Nullable data,
#pragma mark - Public

void IGListPerformDiffWithData(IGListTransitionData *_Nullable data,
UIView *view,
BOOL allowsBackground,
IGListAdaptiveDiffingExperimentConfig adaptiveConfig,
IGListDiffExecutorCompletion completion) {
Expand All @@ -80,7 +93,7 @@ void IGListPerformDiffWithData(IGListTransitionData *_Nullable data,
}

if (adaptiveConfig.enabled) {
_adaptivePerformDiffWithData(data, allowsBackground, adaptiveConfig, completion);
_adaptivePerformDiffWithData(data, view, allowsBackground, adaptiveConfig, completion);
} else {
// Just to be safe, lets keep the original code path intact while adaptive diffing is still an experiment.
_regularPerformDiffWithData(data, allowsBackground, completion);
Expand Down

0 comments on commit f429ec5

Please sign in to comment.