Make yoga & layout specs faster by eliminating some copies (#1128)

This commit is contained in:
Adlai Holler 2018-09-18 07:26:29 -07:00 committed by Huy Nguyen
parent 47e2b9c0de
commit d2984ced8d
7 changed files with 39 additions and 22 deletions

View File

@ -46,6 +46,7 @@
- Unlock before cleanup and calling out to subclass hooks for animated images. [Michael Schneider](https://github.com/maicki) [#1087](https://github.com/TextureGroup/Texture/pull/1087) - Unlock before cleanup and calling out to subclass hooks for animated images. [Michael Schneider](https://github.com/maicki) [#1087](https://github.com/TextureGroup/Texture/pull/1087)
- [ASDisplayNode] Fix interface state update for layer backed nodes when layer thrashes (interface coaleascing case).[Max Wang](https://github.com/wsdwsd0829). [#1111](https://github.com/TextureGroup/Texture/pull/1111) - [ASDisplayNode] Fix interface state update for layer backed nodes when layer thrashes (interface coaleascing case).[Max Wang](https://github.com/wsdwsd0829). [#1111](https://github.com/TextureGroup/Texture/pull/1111)
- [ASPINRemoteImageManager] Add a new API for setting a preconfigured PINRemoteImageManager. [Ernest Ma](https://github.com/ernestmama) [#1124](https://github.com/TextureGroup/Texture/pull/1124) - [ASPINRemoteImageManager] Add a new API for setting a preconfigured PINRemoteImageManager. [Ernest Ma](https://github.com/ernestmama) [#1124](https://github.com/TextureGroup/Texture/pull/1124)
- Small optimization to the layout spec & yoga layout systems by eliminating array copies. [Adlai Holler](https://github.com/Adlai-Holler)
## 2.7 ## 2.7
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877) - Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)

View File

@ -13,6 +13,7 @@
#import <AsyncDisplayKit/_ASDisplayViewAccessiblity.h> #import <AsyncDisplayKit/_ASDisplayViewAccessiblity.h>
#import <AsyncDisplayKit/ASYogaUtilities.h> #import <AsyncDisplayKit/ASYogaUtilities.h>
#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h> #import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h> #import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h> #import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
@ -155,10 +156,12 @@
ASDisplayNodeAssert(childCount == self.yogaChildren.count, ASDisplayNodeAssert(childCount == self.yogaChildren.count,
@"Yoga tree should always be in sync with .yogaNodes array! %@", self.yogaChildren); @"Yoga tree should always be in sync with .yogaNodes array! %@", self.yogaChildren);
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:childCount]; ASLayout *rawSublayouts[childCount];
int i = 0;
for (ASDisplayNode *subnode in self.yogaChildren) { for (ASDisplayNode *subnode in self.yogaChildren) {
[sublayouts addObject:[subnode layoutForYogaNode]]; rawSublayouts[i++] = [subnode layoutForYogaNode];
} }
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:childCount];
// The layout for self should have position CGPointNull, but include the calculated size. // The layout for self should have position CGPointNull, but include the calculated size.
CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode)); CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode));

View File

@ -9,6 +9,7 @@
#import <AsyncDisplayKit/ASAbsoluteLayoutSpec.h> #import <AsyncDisplayKit/ASAbsoluteLayoutSpec.h>
#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASLayout.h> #import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h> #import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>
#import <AsyncDisplayKit/ASLayoutSpecUtilities.h> #import <AsyncDisplayKit/ASLayoutSpecUtilities.h>
@ -64,7 +65,8 @@
}; };
NSArray *children = self.children; NSArray *children = self.children;
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count]; ASLayout *rawSublayouts[children.count];
int i = 0;
for (id<ASLayoutElement> child in children) { for (id<ASLayoutElement> child in children) {
CGPoint layoutPosition = child.style.layoutPosition; CGPoint layoutPosition = child.style.layoutPosition;
@ -77,13 +79,14 @@
ASLayout *sublayout = [child layoutThatFits:childConstraint parentSize:size]; ASLayout *sublayout = [child layoutThatFits:childConstraint parentSize:size];
sublayout.position = layoutPosition; sublayout.position = layoutPosition;
[sublayouts addObject:sublayout]; rawSublayouts[i++] = sublayout;
} }
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];
if (_sizing == ASAbsoluteLayoutSpecSizingSizeToFit || isnan(size.width)) { if (_sizing == ASAbsoluteLayoutSpecSizingSizeToFit || isnan(size.width)) {
size.width = constrainedSize.min.width; size.width = constrainedSize.min.width;
for (ASLayout *sublayout in sublayouts) { for (ASLayout *sublayout in sublayouts) {
size.width = MAX(size.width, sublayout.position.x + sublayout.size.width); size.width = MAX(size.width, sublayout.position.x + sublayout.size.width);
} }
} }

View File

@ -12,6 +12,7 @@
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h> #import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>
#import <AsyncDisplayKit/ASAssert.h> #import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASCollections.h>
static NSUInteger const kForegroundChildIndex = 0; static NSUInteger const kForegroundChildIndex = 0;
static NSUInteger const kBackgroundChildIndex = 1; static NSUInteger const kBackgroundChildIndex = 1;
@ -48,17 +49,19 @@ static NSUInteger const kBackgroundChildIndex = 1;
{ {
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize]; ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:2]; ASLayout *rawSublayouts[2];
int i = 0;
if (self.background) { if (self.background) {
// Size background to exactly the same size. // Size background to exactly the same size.
ASLayout *backgroundLayout = [self.background layoutThatFits:ASSizeRangeMake(contentsLayout.size) ASLayout *backgroundLayout = [self.background layoutThatFits:ASSizeRangeMake(contentsLayout.size)
parentSize:parentSize]; parentSize:parentSize];
backgroundLayout.position = CGPointZero; backgroundLayout.position = CGPointZero;
[sublayouts addObject:backgroundLayout]; rawSublayouts[i++] = backgroundLayout;
} }
contentsLayout.position = CGPointZero; contentsLayout.position = CGPointZero;
[sublayouts addObject:contentsLayout]; rawSublayouts[i++] = contentsLayout;
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];
return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts]; return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts];
} }

View File

@ -113,14 +113,12 @@ ASLayoutElementLayoutCalculationDefaults
{ {
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
[_childrenArray removeAllObjects]; #if ASDISPLAYNODE_ASSERTIONS_ENABLED
NSUInteger i = 0;
for (id<ASLayoutElement> child in children) { for (id<ASLayoutElement> child in children) {
ASDisplayNodeAssert([child conformsToProtocol:NSProtocolFromString(@"ASLayoutElement")], @"Child %@ of spec %@ is not an ASLayoutElement!", child, self); ASDisplayNodeAssert([child conformsToProtocol:NSProtocolFromString(@"ASLayoutElement")], @"Child %@ of spec %@ is not an ASLayoutElement!", child, self);
_childrenArray[i] = child;
i += 1;
} }
#endif
[_childrenArray setArray:children];
} }
- (nullable NSArray<id<ASLayoutElement>> *)children - (nullable NSArray<id<ASLayoutElement>> *)children
@ -291,7 +289,9 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__)
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{ {
NSArray *children = self.children; NSArray *children = self.children;
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count]; let count = children.count;
ASLayout *rawSublayouts[count];
int i = 0;
CGSize size = constrainedSize.min; CGSize size = constrainedSize.min;
for (id<ASLayoutElement> child in children) { for (id<ASLayoutElement> child in children) {
@ -301,9 +301,9 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__)
size.width = MAX(size.width, sublayout.size.width); size.width = MAX(size.width, sublayout.size.width);
size.height = MAX(size.height, sublayout.size.height); size.height = MAX(size.height, sublayout.size.height);
[sublayouts addObject:sublayout]; rawSublayouts[i++] = sublayout;
} }
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];
return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts]; return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts];
} }

View File

@ -10,6 +10,7 @@
#import <AsyncDisplayKit/ASOverlayLayoutSpec.h> #import <AsyncDisplayKit/ASOverlayLayoutSpec.h>
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h> #import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>
#import <AsyncDisplayKit/ASAssert.h> #import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASCollections.h>
static NSUInteger const kUnderlayChildIndex = 0; static NSUInteger const kUnderlayChildIndex = 0;
static NSUInteger const kOverlayChildIndex = 1; static NSUInteger const kOverlayChildIndex = 1;
@ -70,14 +71,17 @@ static NSUInteger const kOverlayChildIndex = 1;
{ {
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize]; ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];
contentsLayout.position = CGPointZero; contentsLayout.position = CGPointZero;
NSMutableArray *sublayouts = [NSMutableArray arrayWithObject:contentsLayout]; ASLayout *rawSublayouts[2];
int i = 0;
rawSublayouts[i++] = contentsLayout;
if (self.overlay) { if (self.overlay) {
ASLayout *overlayLayout = [self.overlay layoutThatFits:ASSizeRangeMake(contentsLayout.size) ASLayout *overlayLayout = [self.overlay layoutThatFits:ASSizeRangeMake(contentsLayout.size)
parentSize:contentsLayout.size]; parentSize:contentsLayout.size];
overlayLayout.position = CGPointZero; overlayLayout.position = CGPointZero;
[sublayouts addObject:overlayLayout]; rawSublayouts[i++] = overlayLayout;
} }
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];
return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts]; return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts];
} }

View File

@ -12,6 +12,7 @@
#import <numeric> #import <numeric>
#import <vector> #import <vector>
#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASDimension.h> #import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASLayout.h> #import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutElement.h> #import <AsyncDisplayKit/ASLayoutElement.h>
@ -151,12 +152,14 @@
self.style.ascender = stackChildren.front().style.ascender; self.style.ascender = stackChildren.front().style.ascender;
self.style.descender = stackChildren.back().style.descender; self.style.descender = stackChildren.back().style.descender;
} }
const auto sublayouts = [[NSMutableArray<ASLayout *> alloc] init]; ASLayout *rawSublayouts[positionedLayout.items.size()];
int i = 0;
for (const auto &item : positionedLayout.items) { for (const auto &item : positionedLayout.items) {
[sublayouts addObject:item.layout]; rawSublayouts[i++] = item.layout;
} }
let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];
return [ASLayout layoutWithLayoutElement:self size:positionedLayout.size sublayouts:sublayouts]; return [ASLayout layoutWithLayoutElement:self size:positionedLayout.size sublayouts:sublayouts];
} }