-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[Performance] Looking for input on tuning performance with AsyncDisplayKit #1446
Comments
hehe. I can promise you this is not ASDK's fault. Why? The iPad 3 has fully 4 times as many pixels to draw, because of Retina - and it has only 1.3x the CPU power, at most. We get almost uninterrupted 60FPS on it with the extremely complex Pinterest feed layout, even with fast scrolling. I'd be thrilled to help you optimize your app, because huge improvements should only take an hour or two of work. We have plans for documentation that will help demonstrate best practices that ensure performance is good on the first try with ASDK, as well as simple steps you can use to quickly dial in performance for your app-specific needs depending on a few details of the UI (e.g. what areas animate, are tappable, etc allows you to flip on very powerful optimizations - isLayerBacking and shouldRasterizeSubnodes are tremendously impactful for performance and you should use them everywhere your app design allows, with only a boolean = YES change in the needed areas) |
cc @levi @maicki @nguyenhuy @hannahmbanana @lappp9 @RCacheaux about the very good point that we need to ensure the documentation we're all working on includes all the details necessary for most app developers to hit 60FPS at least on the iPad 2 and iPhone 4S (iPad 3 or iPhone 4 is a far harder bar) |
Hi @appleguy — if you don't mind putting my use case here directly, I'm using ASDK to help provide a snappier UX recipe cards that look like this: The contents of the cell is held in a @property(nonatomic, strong) ASNetworkImageNode *avatarImageNode;
@property(nonatomic, strong) ASTextNode *authorNameNode;
@property(nonatomic, strong) ASNetworkImageNode *recipeImageNode;
@property(nonatomic, strong) ASTextNode *recipeTitleNode;
@property(nonatomic, strong) MESGradientNode *gradientNode;
@property(nonatomic, strong) ASImageNode *totalDurationIconNode;
@property(nonatomic, strong) ASTextNode *totalDurationTextNode;
@property(nonatomic, strong) ASImageNode *favouritesIconNode;
@property(nonatomic, strong) ASTextNode *favouritesTextNode; ... all in a flat hierarchy. Two network image nodes per cell. They both should fade their images in. Layer-backing / rasterisation seems to interfere with fading in of the placeholders (understandably)! :( The cell itself is called #import "MESMinicardCellNode.h"
#import "MESMinicardContentNode.h"
#import "MESMiniCardViewModel.h"
@interface MESMinicardCellNode ()
@property(nonatomic, strong) ASDisplayNode *contentNode;
@end
@implementation MESMinicardCellNode
- (instancetype)initWithViewModel:(MESMiniCardViewModel *)viewModel {
self = [super init];
if (self) {
_contentNode = [[MESMinicardContentNode alloc] initWithViewModel:viewModel];
_contentNode.cornerRadius = 4;
_contentNode.clipsToBounds = YES;
[self addSubnode:_contentNode];
}
return self;
}
- (void)didLoad {
[super didLoad];
self.clipsToBounds = NO;
self.shadowColor = [UIColor colorWithWhite:0 alpha:0.5].CGColor;
self.shadowOffset = CGSizeMake(0, 1);
self.shadowOpacity = 0.5f;
self.shadowRadius = 1.5f;
// Shadow performance optimization. See https://github.com/facebook/AsyncDisplayKit/issues/980
self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
}
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize {
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[_contentNode]];
}
@end How might you optimize this? Which layers should be rasterised, and which should be layer-backed? Cheers. |
It looks like besides the network images, there are 5 things that could be stuck onto one layer, and rasterized:
But the stuff living on top of the recipe image there can't really be touched, I don't think? |
@fatuhoku Without seeing the code for all of your nodes, my guess is that the corner radius and shadow on the cell adds to the slowness. Also, the gradient and avatar subnodes in your content node can be areas to optimize. Again, without seeing the code, this is just a guess. Good luck and thanks for the code from the other thread! |
@vtsoup Thanks — I figure the gradient is probably pretty expensive to draw that's true. I wonder how we can get around it? And, you're welcome! There's only a handful of LayoutSpecs. It was good fun piecing them together, even though it takes some time. |
@fatuhoku I had a similar problem using layer masks in one of our apps. My solution/workaround was to implement the same visual result using ASDisplayNode and drawing all needed effects. |
@fatuhoku: Indeed the following 4 properties will seriously impact performance on many devices, as they trigger offscreen rendering which forces the GPU to switch context repeatedly on every frame:
@EviluS has the right idea here. Drawing the shadow in a more manual way would significantly help. The way that the Paper app achieves these effects is to use thin, stretchable images for each side of the shadow effect (these elements can be layer backed or sometimes even rasterized). A final thing you should consider is if the UI behavior should be tweaked depending on the performance of a device. For example, the second most expensive thing here is the fade in animations as images load. The iPad 2 is a fairly slow device and the overall user experience may be superior if this particular effect is disabled. If you choose to do this, you would also want to disable it for the iPad 3 (which is slower than the iPad 2 due to the retina display) and also the iPad mini 1. Apologies for the delay! I'm going to close this issue since, but feel free to reopen for further questions. |
Hi @appleguy and @EviluS! I found this discussion after trying to add a shadow to my ASCellNode. In my case, the image is the background of my cell, which features both rounded corners and drop shadows, so I actually apply the effect to the image node itself. So with the first case — achieving rounded corners — I was manage to do ok, using the pre-composited opaque corners technique, like this:
But I’m not sure about the way to go with the shadow. @appleguy, how would the stretchable image will look in my case? Not sure about the directions I should give to my designer 🤔 Would love for your help... Thanks! |
@oferRounds The stretchable image should probably be 1px of width and you should stretch horizontally. |
@EviluS missed your comment back then – thanks a lot! |
I used RRFPSBar to measure the performance of my
ASCollectionView
and found that while the iPad Air manages to maintain a steady 60FPS, the iPad 2 struggles much more. There are down-spikes going down to around 7 FPS at times.The iPad 2 is a multi-core device and I expected that ASDK would bring performance benefits.
I was wondering what have been your experiences when working with slower devices like the iPad 2?
The text was updated successfully, but these errors were encountered: