Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Sep 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- [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)
- Small optimization to the layout spec & yoga layout systems by eliminating array copies. [Adlai Holler](https://github.com/Adlai-Holler)

## 2.7
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)
Expand Down
7 changes: 5 additions & 2 deletions Source/ASDisplayNode+Yoga.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#import <AsyncDisplayKit/_ASDisplayViewAccessiblity.h>
#import <AsyncDisplayKit/ASYogaUtilities.h>
#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
Expand Down Expand Up @@ -155,10 +156,12 @@ - (void)setupYogaCalculatedLayout
ASDisplayNodeAssert(childCount == self.yogaChildren.count,
@"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) {
[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.
CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode));
Expand Down
11 changes: 7 additions & 4 deletions Source/Layout/ASAbsoluteLayoutSpec.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#import <AsyncDisplayKit/ASAbsoluteLayoutSpec.h>

#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>
#import <AsyncDisplayKit/ASLayoutSpecUtilities.h>
Expand Down Expand Up @@ -64,7 +65,8 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
};

NSArray *children = self.children;
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count];
ASLayout *rawSublayouts[children.count];
int i = 0;

for (id<ASLayoutElement> child in children) {
CGPoint layoutPosition = child.style.layoutPosition;
Expand All @@ -77,13 +79,14 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize

ASLayout *sublayout = [child layoutThatFits:childConstraint parentSize:size];
sublayout.position = layoutPosition;
[sublayouts addObject:sublayout];
rawSublayouts[i++] = sublayout;
}

let sublayouts = [NSArray<ASLayout *> arrayByTransferring:rawSublayouts count:i];

if (_sizing == ASAbsoluteLayoutSpecSizingSizeToFit || isnan(size.width)) {
size.width = constrainedSize.min.width;
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);
}
}

Expand Down
9 changes: 6 additions & 3 deletions Source/Layout/ASBackgroundLayoutSpec.mm
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>

#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASCollections.h>

static NSUInteger const kForegroundChildIndex = 0;
static NSUInteger const kBackgroundChildIndex = 1;
Expand Down Expand Up @@ -48,17 +49,19 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];

NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:2];
ASLayout *rawSublayouts[2];
int i = 0;
if (self.background) {
// Size background to exactly the same size.
ASLayout *backgroundLayout = [self.background layoutThatFits:ASSizeRangeMake(contentsLayout.size)
parentSize:parentSize];
backgroundLayout.position = CGPointZero;
[sublayouts addObject:backgroundLayout];
rawSublayouts[i++] = backgroundLayout;
}
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];
}

Expand Down
16 changes: 8 additions & 8 deletions Source/Layout/ASLayoutSpec.mm
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,12 @@ - (void)setChildren:(NSArray<id<ASLayoutElement>> *)children
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");

[_childrenArray removeAllObjects];

NSUInteger i = 0;
#if ASDISPLAYNODE_ASSERTIONS_ENABLED
for (id<ASLayoutElement> child in children) {
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
Expand Down Expand Up @@ -291,7 +289,9 @@ - (instancetype)initWithLayoutElements:(NSArray<id<ASLayoutElement>> *)layoutEle
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
NSArray *children = self.children;
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count];
let count = children.count;
ASLayout *rawSublayouts[count];
int i = 0;

CGSize size = constrainedSize.min;
for (id<ASLayoutElement> child in children) {
Expand All @@ -301,9 +301,9 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
size.width = MAX(size.width, sublayout.size.width);
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];
}

Expand Down
8 changes: 6 additions & 2 deletions Source/Layout/ASOverlayLayoutSpec.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import <AsyncDisplayKit/ASOverlayLayoutSpec.h>
#import <AsyncDisplayKit/ASLayoutSpec+Subclasses.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASCollections.h>

static NSUInteger const kUnderlayChildIndex = 0;
static NSUInteger const kOverlayChildIndex = 1;
Expand Down Expand Up @@ -70,14 +71,17 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];
contentsLayout.position = CGPointZero;
NSMutableArray *sublayouts = [NSMutableArray arrayWithObject:contentsLayout];
ASLayout *rawSublayouts[2];
int i = 0;
rawSublayouts[i++] = contentsLayout;
if (self.overlay) {
ASLayout *overlayLayout = [self.overlay layoutThatFits:ASSizeRangeMake(contentsLayout.size)
parentSize:contentsLayout.size];
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];
}

Expand Down
9 changes: 6 additions & 3 deletions Source/Layout/ASStackLayoutSpec.mm
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <numeric>
#import <vector>

#import <AsyncDisplayKit/ASCollections.h>
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
Expand Down Expand Up @@ -151,12 +152,14 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
self.style.ascender = stackChildren.front().style.ascender;
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) {
[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];
}

Expand Down