Layer Trees vs. Flat Drawing: Graphics Performance Across iOS Device Generations
floriankugler.com
floriankugler.com
We used all UIKit elements like UIViews, UIImageViews, and just core-animationed everything around. It's amazing because you can have 50 towers on screen, all playing their firing animation, along with 100+ monsters walking with their animations.. and it handles well.
The reason we actually chose UIKit (over Cocos2D or OpenGL etc) was (1) my experience in it from app development, but (2) more importantly being able to use Apple's UI widgets. Like scrollviews, gesture-recognizers, etc... rather than try to write our own (I'm sure we've all played iOS games with weird UIs that are kind of like Apple's but fall short). Also, (3) was the speed of getting something working (kind of related to (1) for me).
Downsides are that there's no blending effects like 'additive' for lights/effects, and also it's not trivial to pause a game when it's running timers and core-animation separately (we do have a game loop for logic, but the monsters them-self just move on GPU-based core animations). I'd like to STRESS that using UIKit for most games is probably not a good idea.
Anyway, thought it might interest some people to hear this :)
Oh, and another benefit is no load screens.
Not having to load many Retina-sized background images for UI elements would significantly decrease memory pressure on the OS as well as increase responsiveness.
NB. Assuming older devices will be able to upgrade and that texture-heavy UI elements would be phased out.
Edit: Typo
A lot of people like to use CSS3 for no reason, and it's actually a huge burden on some devices. And that's disregarding the backwards compatibility aspect altogether.
Just as images and assets can be a pain for data plans and low bandwidth, "fanciness" can be a rendering bottleneck.
[1]: http://dev.opera.com/articles/view/beautiful-ui-styling-with...
The biggest impact would be seen on iPads, because iPad 3 actually took a step backwards in terms in performance behind iPad 2, when it switched to retina, and iPad 4 barely matches iPad 2 in performance (if we're comparing native iPad 2 apps vs native "retina" iPad 4 apps).
It could also be the reason why the next iPad is rumored to not have a huge battery anymore, like iPad 3 and iPad 4, and be much slimmer (the last 2 iPads were thicker than iPad 2).
For the most part it is very responsive, but it does get bogged down here and there. For example if I get a text from someone while I'm typing a text to a different person and click the notification ribbon, the phone will hang for a second or two before switching to the other person's text. Is that common on all iOS devices? I'd always imagined it should be much faster given that the Message app is already loaded and active.
In other words, the comparison is between the CPU redrawing a gradient 60x a second, and, an image being moved around on screen. Not entirely surprising that the one that does less rendering is going to be faster.
I suspect (but can't confirm without the source code to the demo) that shouldRasterize would actually hurt performance in one of the two cases in the article. Specifically, I imagine that it would make the score for adding and removing views from screen even worse than it already is.
Yes, it renders into a bitmap, and reduces CPU usage, once you've paid the upfront rendering cost. But, it doesn't rasterize opacity, and, will use up a ton of memory (because it doesn't result in stretchable images).
I'd love to hear others thoughts on how they use -drawRect nowadays.
When you do anything in Core Animation in -drawRect, that throws all drawing on CPU, instead of dividing the work between the CPU and GPU. Which, in one project where I was doing Core Animation alongside OpenGL, that had some very bad consequences.
Core Animation is pretty interesting. Internally, it does some drawing with Core Graphics, but that's only if you use certain features (i.e., use of CAShapeLayers, anything involving shadows)... and even then, CG is pretty darned fast.
I've found CAShapeLayers can be a bit of a resource hog, but since those resources tend to be thrown behind 60 fps animation, that might not be such a problem.
The CAShapeLayer issues only came up when I tried scrolling within a scroll view that contained a CAShapeLayer with a CGPath that had 20 points defining lines. Setting the CAShapeLayer to -shouldRasterize:YES after the animation completed "fixed" the issue, as long as you didn't need to scroll while the CAShapeLayer was animating.
(Don't even bother animating a CAShapeLayer while -shouldRasterize: is set to YES. That just causes even more fun problems with dropped frames.)
Another note with -drawRect and animations, I messed around with CADisplayLink and -drawRect to make animations. Beware of doing this, it was a performance hog. It was a simple animation in a large rect, and by the time I had optimized the drawing area, I could have finished the entire project.
I wonder, would CAShapeLayer become more of a resource hog with more points in the path (or more complex arcs), or does it happen with the overall size of the path?
(Hi oc, its Ryan!)
A couple of things I've found work very well are:
1) not creating deep view hierarchies in your table cells - ie. keep those very flat.'
2) Make your images as small as possible in terms of file size. Do background processing to make them smaller and lower the quality if you don't need it. This is by far the easiest way to increase speed if you aren't doing it already.
While its great to have a small image that doesn't require much I/O to read, "small" shouldn't only refer to file size.
Instead, a "small" image should be one that has a small resolution, and is stretchable. This lets the GPU tile the portions of the image that are being stretched and reuse GPU memory, instead of having to waste space in ram to hold duplicate pixel data.
(And when something's as small as it can be, it doesn't minify very well anymore -- not much left to strip from the PNG.)
thanks for posting, florian!