diff --git a/CHANGELOG.md b/CHANGELOG.md index fe8b26cb6..27bcc41c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/Source/ASDisplayNode+Yoga.mm b/Source/ASDisplayNode+Yoga.mm index fedff84cf..d1d3d7def 100644 --- a/Source/ASDisplayNode+Yoga.mm +++ b/Source/ASDisplayNode+Yoga.mm @@ -13,6 +13,7 @@ #import #import +#import #import #import #import @@ -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 arrayByTransferring:rawSublayouts count:childCount]; // The layout for self should have position CGPointNull, but include the calculated size. CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode)); diff --git a/Source/Layout/ASAbsoluteLayoutSpec.mm b/Source/Layout/ASAbsoluteLayoutSpec.mm index b91b5d4ef..e5edb272d 100644 --- a/Source/Layout/ASAbsoluteLayoutSpec.mm +++ b/Source/Layout/ASAbsoluteLayoutSpec.mm @@ -9,6 +9,7 @@ #import +#import #import #import #import @@ -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 child in children) { CGPoint layoutPosition = child.style.layoutPosition; @@ -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 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); } } diff --git a/Source/Layout/ASBackgroundLayoutSpec.mm b/Source/Layout/ASBackgroundLayoutSpec.mm index 7f969215c..30664fd92 100644 --- a/Source/Layout/ASBackgroundLayoutSpec.mm +++ b/Source/Layout/ASBackgroundLayoutSpec.mm @@ -12,6 +12,7 @@ #import #import +#import static NSUInteger const kForegroundChildIndex = 0; static NSUInteger const kBackgroundChildIndex = 1; @@ -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 arrayByTransferring:rawSublayouts count:i]; return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts]; } diff --git a/Source/Layout/ASLayoutSpec.mm b/Source/Layout/ASLayoutSpec.mm index 4bebb094b..dc8827d70 100644 --- a/Source/Layout/ASLayoutSpec.mm +++ b/Source/Layout/ASLayoutSpec.mm @@ -113,14 +113,12 @@ - (void)setChildren:(NSArray> *)children { ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - [_childrenArray removeAllObjects]; - - NSUInteger i = 0; +#if ASDISPLAYNODE_ASSERTIONS_ENABLED for (id 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> *)children @@ -291,7 +289,9 @@ - (instancetype)initWithLayoutElements:(NSArray> *)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 child in children) { @@ -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 arrayByTransferring:rawSublayouts count:i]; return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts]; } diff --git a/Source/Layout/ASOverlayLayoutSpec.mm b/Source/Layout/ASOverlayLayoutSpec.mm index 84ca72a9c..f1cbe4884 100644 --- a/Source/Layout/ASOverlayLayoutSpec.mm +++ b/Source/Layout/ASOverlayLayoutSpec.mm @@ -10,6 +10,7 @@ #import #import #import +#import static NSUInteger const kUnderlayChildIndex = 0; static NSUInteger const kOverlayChildIndex = 1; @@ -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 arrayByTransferring:rawSublayouts count:i]; return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts]; } diff --git a/Source/Layout/ASStackLayoutSpec.mm b/Source/Layout/ASStackLayoutSpec.mm index 1cf9ce3d0..93a693b1c 100644 --- a/Source/Layout/ASStackLayoutSpec.mm +++ b/Source/Layout/ASStackLayoutSpec.mm @@ -12,6 +12,7 @@ #import #import +#import #import #import #import @@ -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 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 arrayByTransferring:rawSublayouts count:i]; return [ASLayout layoutWithLayoutElement:self size:positionedLayout.size sublayouts:sublayouts]; }