Skip to content

Commit

Permalink
Make yoga & layout specs faster by eliminating some copies (#1128)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adlai-Holler authored and nguyenhuy committed Sep 18, 2018
1 parent 47e2b9c commit d2984ce
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 22 deletions.
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

0 comments on commit d2984ce

Please sign in to comment.