Merge pull request #1239 from rahul-malik/rmalik-concurrent-alloc

[ASDataController] Concurrent allocation of ASCellNodes
This commit is contained in:
appleguy 2016-02-17 22:53:35 -08:00
commit c526fcdff4
4 changed files with 29 additions and 9 deletions

View File

@ -655,7 +655,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0) scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0)
); );
[self handleBatchFetchScrollingToOffset:*targetContentOffset]; if (targetContentOffset != NULL) {
[self handleBatchFetchScrollingToOffset:*targetContentOffset];
}
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; [_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];

View File

@ -638,7 +638,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0) scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0)
); );
[self handleBatchFetchScrollingToOffset:*targetContentOffset]; if (targetContentOffset != NULL) {
[self handleBatchFetchScrollingToOffset:*targetContentOffset];
}
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; [_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];

View File

@ -162,22 +162,35 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
} }
NSUInteger nodeCount = nodes.count; NSUInteger nodeCount = nodes.count;
NSMutableArray<ASCellNode *> *allocatedNodes = [NSMutableArray arrayWithCapacity:nodeCount]; NSMutableArray<ASCellNode *> *allocatedNodes = [NSMutableArray<ASCellNode *> arrayWithCapacity:nodeCount];
dispatch_group_t layoutGroup = dispatch_group_create(); dispatch_group_t layoutGroup = dispatch_group_create();
ASSizeRange *nodeBoundSizes = (ASSizeRange *)malloc(sizeof(ASSizeRange) * nodeCount); ASSizeRange *nodeBoundSizes = (ASSizeRange *)malloc(sizeof(ASSizeRange) * nodeCount);
for (NSUInteger j = 0; j < nodes.count && j < indexPaths.count; j += kASDataControllerSizingCountPerProcessor) { for (NSUInteger j = 0; j < nodes.count && j < indexPaths.count; j += kASDataControllerSizingCountPerProcessor) {
NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j); NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j);
__block NSArray *subarray;
// Allocate nodes concurrently.
dispatch_block_t allocationBlock = ^{ dispatch_block_t allocationBlock = ^{
for (NSUInteger k = j; k < j + batchCount; k++) { __strong ASCellNode **allocatedNodeBuffer = (__strong ASCellNode **)calloc(batchCount, sizeof(ASCellNode *));
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(batchCount, queue, ^(size_t i) {
unsigned long k = j + i;
ASCellNodeBlock cellBlock = nodes[k]; ASCellNodeBlock cellBlock = nodes[k];
ASCellNode *node = cellBlock(); ASCellNode *node = cellBlock();
ASDisplayNodeAssertNotNil(node, @"Node block created nil node"); ASDisplayNodeAssertNotNil(node, @"Node block created nil node");
[allocatedNodes addObject:node]; allocatedNodeBuffer[i] = node;
if (!node.isNodeLoaded) { if (!node.isNodeLoaded) {
nodeBoundSizes[k] = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPaths[k]]; nodeBoundSizes[k] = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPaths[k]];
} }
});
subarray = [[NSArray alloc] initWithObjects:allocatedNodeBuffer count:batchCount];
// Nil out buffer indexes to allow arc to free the stored cells.
for (int i = 0; i < batchCount; i++) {
allocatedNodeBuffer[i] = nil;
} }
free(allocatedNodeBuffer);
}; };
if (ASDisplayNodeThreadIsMain()) { if (ASDisplayNodeThreadIsMain()) {
@ -187,14 +200,16 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
dispatch_semaphore_signal(sema); dispatch_semaphore_signal(sema);
}); });
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
[self layoutLoadedNodes:[allocatedNodes subarrayWithRange:NSMakeRange(j, batchCount)] ofKind:kind atIndexPaths:[indexPaths subarrayWithRange:NSMakeRange(j, batchCount)]]; [self layoutLoadedNodes:subarray ofKind:kind atIndexPaths:[indexPaths subarrayWithRange:NSMakeRange(j, batchCount)]];
} else { } else {
allocationBlock(); allocationBlock();
[_mainSerialQueue performBlockOnMainThread:^{ [_mainSerialQueue performBlockOnMainThread:^{
[self layoutLoadedNodes:[allocatedNodes subarrayWithRange:NSMakeRange(j, batchCount)] ofKind:kind atIndexPaths:[indexPaths subarrayWithRange:NSMakeRange(j, batchCount)]]; [self layoutLoadedNodes:subarray ofKind:kind atIndexPaths:[indexPaths subarrayWithRange:NSMakeRange(j, batchCount)]];
}]; }];
} }
[allocatedNodes addObjectsFromArray:subarray];
dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (NSUInteger k = j; k < j + batchCount; k++) { for (NSUInteger k = j; k < j + batchCount; k++) {
ASCellNode *node = allocatedNodes[k]; ASCellNode *node = allocatedNodes[k];

View File

@ -166,6 +166,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\
} }
- (BOOL)resignFirstResponder { - (BOOL)resignFirstResponder {
[super resignFirstResponder];
if (self.isFirstResponder) { if (self.isFirstResponder) {
self.isFirstResponder = NO; self.isFirstResponder = NO;
return YES; return YES;