Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Pursuing 60 fps

No description
by

Tamas Zahola

on 11 March 2016

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Pursuing 60 fps

Pursuing 60 fps scrolling
Tamás Zahola
github.com/tzahola

Our task
Write a business card browser for iPad

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Cell* cell = [collectionView
dequeueReusableCellWithReuseIdentifier:NSStringFromClass([Cell class])
forIndexPath:indexPath];
cell.data = self.data[indexPath.row];
return cell;
}
@interface Cell : UICollectionViewCell

@property (weak, nonatomic) IBOutlet UIView *backgroundRoundedRectView;
@property (weak, nonatomic) IBOutlet UIView *backgroundShadowView;

@property (weak, nonatomic) IBOutlet UIView *imageViewMaskView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UILabel *firstNameLabel;
@property (weak, nonatomic) IBOutlet UILabel *lastNameLabel;
@property (weak, nonatomic) IBOutlet UILabel *phoneNumberLabel;

@property (nonatomic, strong) Data* data;

@end
@implementation Cell

- (void)setData:(Data *)data {
if (_data == data) {
return;
}
_data = data;

self.firstNameLabel.text = data.firstName;
self.lastNameLabel.text = data.lastName;
self.phoneNumberLabel.text = data.phoneNumber;

self.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:data.imageURL]];
}

- (void)p
repareForReuse {
[super prepareForReuse];
self.data = nil;
}

- (void)awakeFromNib {
[super awakeFromNib];

self.imageViewMaskView.layer.masksToBounds = YES;
self.imageViewMaskView.layer.cornerRadius = 5;

self.backgroundRoundedRectView.backgroundColor = [UIColor whiteColor];
self.backgroundRoundedRectView.layer.masksToBounds = YES;
self.backgroundRoundedRectView.layer.cornerRadius = 5;

self.backgroundShadowView.layer.shadowColor = [UIColor blackColor].CGColor;
self.backgroundShadowView.layer.shadowOffset = CGSizeMake(0, 5);
self.backgroundShadowView.layer.shadowRadius = 3;
self.backgroundShadowView.layer.shadowOpacity = 0.7;
}

@end
- (void)setData:(Data *)data {
if (_data == data) {
return;
}
_data = data;

self.firstNameLabel.text = data.firstName;
self.lastNameLabel.text = data.lastName;
self.phoneNumberLabel.text = data.phoneNumber;


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage* image = [UIImage imageWithData:[NSData dataWithContentsOfURL:data.imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});

}
The easy fix
Is this good enough?
"There are no two words in the English language more harmful than 'good job'." – Terence Fletcher
"There are no two words in software development more harmful than 'good enough'." – Yours truly :P
With
traditional tools
(i.e. don't use a cannon to kill a fly. hint: cannon = AsyncDisplayKit)
Let's see what we can do
Even with
layer.shouldRasterize = YES
it cannot beat the good old 9-patch image.
Forget CALayer shadow
The solid background makes alpha bending obslete too.
Eliminate off-screen rendering
CALayer = texture
CALayer
texture
(aka backing store)
-display / -setContents:
update
(upload or
render
)
Off-screen rendering
CALayer
-display / -setContents:
GPU
texture
texture
texture
render
GPU
to screen
to screen
upload
upload
texture
(aka backing store)
What triggers off-screen rendering?
layer.masksToBounds = YES
layer.shouldRasterize = YES
layer.shadow...
layer.mask = ...
Baked-in effects
baked-in shadow & rounded-rect background via 9-patch image
image corners masked w/ PNGs
Are we finished yet?
Let's profile!
But we didn't ask for re-layout!
UILabel :(
CATextLayer ;)
Still not quite right...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage* image = [UIImage imageWithData:[NSData dataWithContentsOfURL:data.imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});
On the main thread???
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage* image = [UIImage imageWithData:[NSData dataWithContentsOfURL:data.imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)data.imageURL, NULL);

CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0,
(CFDictionaryRef)@{
(NSString*)kCGImageSourceShouldCache : @YES,
(NSString*)kCGImageSourceShouldCacheImmediately : @YES)
});
CFRelease(source);
UIImage* image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);

dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)data.imageURL, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0,
(CFDictionaryRef)@{
(NSString*)kCGImageSourceShouldCache : @YES,
(NSString*)kCGImageSourceShouldCacheImmediately : @YES)
});
CFRelease(source);

dispatch_async(dispatch_get_main_queue(), ^{

self.imageLayerView.layer.contents = cgImage;
CGImageRelease(cgImage);
});
});
Turns out when we wrote this...
... we meant this.
or this.
not quite...
Almost there
PNG
JPEG
slow
DEFLATE (zip kind of)
fast
DCT (MPEG kind of)
hardware accelerated
Recap
github.com/tzahola/Scrolling60fps
Try it yourself!
Thank you!
Q&A
Full transcript