Open christianselig opened 5 years ago
@christianselig Hey - would be interesting to see if this one could maybe help you: https://github.com/TextureGroup/Texture/pull/1469. It's on master only yet, but if you would point to that. Also if you run it within Instruments what is taking up the memory?
@maicki I assume it's not implicitly activated, right? (It's an experimental feature, ASExperimentalDrawingGlobal
?) If so, how exactly do I activate that, haha? I'm seeing some stuff around ASConfigurationManager
but having trouble finding anything exact…
@christianselig Do something like that in your AppDelegate:
@implementation ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration {
ASConfiguration *cfg = [[ASConfiguration alloc] init];
cfg.experimentalFeatures |= ASExperimentalDrawingGlobal;
return cfg;
}
@end
@maicki Sorry I'm still a little lost and trying to put this into Swift, is that just a category on ASConfiguration
, and it internally looks for a function called textureConfiguration
? It's not a protocol or anything?
EDIT: Just a sec actually I'll just rewrite this in Objective-C haha, my Objective-C to Swift conversion isn't the best.
@maicki
Okay, pointed my Podfile to the master branch, rewrote it in Objective-C (see below) and added that code to the AppDelegate.
The result was the same, crashed with the following message:
Message from debugger: Terminated due to memory issue
Whereas the UIKit version worked.
Objective-C version:
#import "ViewController.h"
#import "AsyncDisplayKit/AsyncDisplayKit.h"
#import "PINRemoteImage/PINRemoteImage.h"
@interface ViewController ()
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) ASImageNode *imageNode;
@property (nonatomic, strong) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.frame = self.view.bounds;
self.scrollView.backgroundColor = [UIColor blackColor];
self.scrollView.delegate = self;
[self.view addSubview:self.scrollView];
NSURL *url = [NSURL URLWithString:@"https://preview.redd.it/jlwba6iohkt21.jpg?auto=webp&s=2da20d8e4e24fbbd654a3c002de93d8521062648"];
CGSize imageSize = CGSizeMake(12283.0, 12283.0);
[[[ASPINRemoteImageDownloader sharedDownloader] sharedPINRemoteImageManager] downloadImageWithURL:url options:PINRemoteImageManagerDownloadOptionsSkipDecode completion:^(PINRemoteImageManagerResult * _Nonnull result) {
NSLog(@"Download complete!");
if (!result.image) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
// Toggle this if you want to use UIKit instead of AsyncDisplayKit
BOOL useAsyncDisplayKit = YES;
if (useAsyncDisplayKit) {
ASImageNode *imageNode = [[ASImageNode alloc] init];
imageNode.frame = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
imageNode.image = result.image;
self.imageNode = imageNode;
[self.scrollView addSubview:imageNode.view];
} else {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
imageView.image = result.image;
self.imageView = imageView;
[self.scrollView addSubview:imageView];
}
CGFloat scaleToFit = fminf(self.scrollView.bounds.size.width / imageSize.width, self.scrollView.bounds.size.height / imageSize.height);
self.scrollView.contentSize = imageSize;
self.scrollView.minimumZoomScale = scaleToFit;
self.scrollView.maximumZoomScale = 1.0;
self.scrollView.zoomScale = scaleToFit;
});
}];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
if (self.imageNode) {
return self.imageNode.view;
}
return self.imageView;
}
@end
And the AppDelegate.m:
#import "AppDelegate.h"
#import "AsyncDisplayKit/AsyncDisplayKit.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
@end
@implementation ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration {
ASConfiguration *cfg = [[ASConfiguration alloc] init];
cfg.experimentalFeatures |= ASExperimentalDrawingGlobal;
return cfg;
}
@end
I profiled it in Instruments in both the Swift version (without the experimental feature) and the Objective-C version with the experimental feature and both seemed the same with createContentsForKey
seemingly taking the lions share of memory usage in ASImageNode.mm.
Full Swift (non-experiment) call stack/memory used:
Full Objective-C (experiment) stack:
I have 10000 records, the memory was 40M if I didn't add ASImageNode
, but it was 150M if I added ASImageNode
(didn't set an image to it) and if I scrolled the ASCollectionView, the memory was up and up.
Using Texture 2.8.1. (Also mentioned in Slack)
I’m having a heck of a time figuring out how to get Texture (specifically
ASImageNode
) to work well with a very large image download. Specifically this image from Reddit.I haven’t had any trouble with UIKit (
UIImageView
) which uses 250MB of RAM to render the image, but Texture peaks at about 1.5GB before levelling back down to around 20MB. Unfortunately this means it crashes most devices due to excessive memory usage, and even my iPhone X gets multiple memory warnings (though it doesn't crash).The image is being shown in a
UIScrollView
and the image is about 6MB and 12,000 x 12,000. I created a sample project with just a small bit of code that maps the UIKit implementation to Texture. (Note the scroll view isn't inherently necessary and the issue is visible without it.)I'm sure I'm just doing something silly, and to be fair I'm not understating the complex nature of image rendering! I've just found in the past Texture always performs very favorably to UIKit so something seemed odd. It might be possible that
UIImageView
loads the image into memory only in visible tiles?Code:
Sample Project: LargeImageTextureTest.zip