Optimization lot of UIImageView - ios

I run into an optimization problem. I have a to display a lot of image a the same time on the screen (up to 150). These image are displayed like if it was a sphere, that can roll.
So far it run 60 fps on a new device, but there is some micro lags and I don't know what is the cause. The profiler tell me 59-60 fps but the problem is that the missing fps is visible and fell like a micro-slutter.
If I reduce the number of imageViews drastically, this problem disappear.
It doesn't seems to be gpu-limited, because I use something like 30% at most of the gpu, but the cpu never goes to more than 50% neither.
What could cause that/how can I detect the cause of this micro lag ? (the image are inited with contentOfFile)
What is the best solution to improve performance knowing that at least half of the image are not on the screen (other side of the sphere) ?
-Recycle UIImageViews
-Set not showed imageView to hidden (it's what i'm doing right now)
-Use rasterization layer (But since the size is changing everytime, it will re-render, right ?)
-Another magic solution that i'm not aware of.
If you want to try the app :
https://itunes.apple.com/us/app/oolala-instant-hangout-app/id972713282?mt=8

1) The way those shapes are created is also important. The most performant way to do that (that's I'm aware of) would be to pre-render images with alpha channel.
2) There is also a "classic" jpeg decompression problem
3) We used CALayer directly to render ~300 images in a UIScrollView on iPhone 4S screen without dropped frames. Might give it a shot.
_layer = [CALayer new];
_layer.contents = (id)_image.CGImage;
_layer.opaque = _opaque;
_layer.contentsScale = [UIScreen mainScreen].scale;
It was a long time ago and was used on iOS 5. You should probably disregard this suggestion unless you have a fast way to test it.

Related

One image with alpha lagging spritekit

I am making a game, and it involves a sandstorm. I decided that the basic concept would be that I would make an image that looks roughly like a sandstorm, and then decorate it with some particles/whatever else it takes.
I ran into an issue at step one. I threw together a simple image for testing purposes:
I added that to my game, and the FPS dropped by 60%. I was surprised by the effect one image had, but I wasn't too worried about it. I cut the resolution of the image in half, and again, lots of lag.
Is spritekit/iOS really that bad at handling moderately sized images with alpha? I read on another question that the simulator is bad at rendering, but that can't be the entire problem.
Is there any hope for getting this to render without slicing my performance? The particles work well, everything else runs at 60fps just fine, but the addition of this image is apparently a severe drain on resources.
EDIT: I tested my game out on my phone, and I got no lag. So apparently, the simulator is just really bad at rendering after all. At the same time, I am curious as to how to speed up performance, as there is clearly some kind of lag going on.
I'm no expert on SpriteKit, but I had similar experiences with plain core animation and layering.
The issue is that an image with alpha, even for the "opaque" parts of it, it introduces a redrawing call on all the sublayers underneath it for every time it moves. First check if this is actually the problem, and then, try one of this, and see if it improves:
SKCropNode could prevent for rendering the underneath elements
Tile the image so only the border has alpha
Snapshot the underneath layers.
Reduce the amount of nodes being rendered, hide the ones that are "under the sandstorm".
And you should be using real devices to test performance of your game, you cannot rely on the simulator for that.

Long and full-screen animation with UIImageView

I just crashed against the fact that cramming 60 960x640 PNG files into an UIImageView is a terrible mistake.
That said, I'm still required to show this animation, and since it's supposed to have a transparent background, I can't go for a MPMoviePlayer or something like that (or can I?). Besides, even if I could separate the different elements of the animation (which I can't without going to the guy who gave it to me) most of them are still quite large.
I'm at a complete loss for ideas. Do you have any?
Sounds like you might be better suited playing a video, but I'm not sure about the transparent background. Using separate pngs, you have to load each one into memory, which is (640 * 960) pixels * 24 bits/pixels * 60 images = a lot of memory.
That said, how fast do you need to play the animation? Instead of using UIImageView animations, you could use a timer and manually manage loading and unloading of the images into memory, only keeping around one or two at a time.

Faster Alternatives to UIImageView in iOS

I have a list of png images that I want them to show one after another to show an animation. In most of my cases I use a UIImageView with animationImages and it works fine. But in a couple of cases my pngs are 1280*768 (full screen iPad) animations with 100+ frames. I see that using the UIImageView is quite slow on the emulator (too long to load for the first time) and I believe that if I put it on the device it will be even slower.
Is there any alternative that can make show an image sequence quite smoothly? Maybe Core Animation? Is there any working example I can see?
Core Animation can be used for vector/key-frame based animation - not image sequences. Loading over a hundred full-screen PNGs on an iPad is a really bad idea, you'll almost certainly get a memory warning if not outright termination.
You should be using a video to display these kind of animations. Performance will be considerably better. Is there any reason why you couldn't use a H.264 video for your animation?
Make a video of your pictures. It is the simplest and probably most reasonable approach.
If you want really good performance and full control over your animation, you can convert the pictures to pvrtc4 format and draw them as billboards (textured sprites) with OpenGL. This can be a lot of work if you don't know how to do it.
Look at the second example
http://www.modejong.com/iPhone/
Extracts from http://www.modejong.com/iPhone/
There is also the UIImageView.animationImages API, but it quickly sucks up all the system memory when using more than a couple of decent size images.
I wanted to show a full screen animation that lasts 2 seconds, at 15 FPS that is a total of 30 PNG images of size 480x320. This example implements an animation oriented view controller that simply waits to read the PNG image data for a frame until it is needed.
Instead of alllocating many megabytes, this class run in about a half a meg of memory with about a 5-10% CPU utilization on a 2nd gen iPhone. This example has also been updated to include the ability to optionally play an audio file via AVAudioPlayer as the animation is displayed.

iOS Animated Logo -- Low memory alternatives

I have a three-second PNG sequence (a logo animation) that I'd like to display right after my iOS app launches. Since this is the only animated sequence in the app, I'd prefer not to use Cocos2D.
But with UIImageView's animationImages, the app runs out of memory on iPod Touch devices.
Is there more memory-conscious/efficient way to show this animation? Perhaps a sprite sheet class that doesn't involve Cocos2D? Or something else?
If this is an animated splash screen or similar, note that the HIG frowns on such behavior (outside of fullscreen games, at least).
If you're undeterred by such arguments (or making a game), you might consider saving your animation as an MPEG-4 video and using MPMoviePlayerController to present it. With a good compressor, it should be possible to get the size and memory usage down quite a lot and still have a good quality logo animation.
I doubt you're going to find much improvement any other way -- a sprite sheet, for example, is still going to be doing the same kind of work as as sequence of PNGs. The problem is that for most animations, a lot of the pixels are untouched from frame to frame... if you're presenting it just as a series of images, you're wasting a lot of time and space on temporally duplicated pixels. This is why we have video codecs.
You could try manually loading/unloading the png images as needed. I don't know what your frame rate requirements are. Also, consider a decent-quality jpg or animated gif. And you can always make the image smaller so it doesn't take up the whole screen. Just a few thoughts.

CATiledLayer and UIImageView what's the big deal between them?

few months ago I've found a really awesome sample code from Apple site. The sample is called "LargeImageDownsizing" the wonderful thing is that it explain a lot about how image are read from resources and then rendered on screen. Digging into that code I've found something that is disturbing me a little. The downsized image is passed to a view that has a CATiledLayer, but without giving a piece of image at each tile to improve memory performance, it just set the tile size and then load image (I'm making things simple to go to the concept). So my question basically is why?Why use a CATiledLayer if it is not feed in the right way, they could have used a normal UIImageView... So I made few tests to understand if I was right. Modifing the code simple adding a scrollview with an image view as subview and responding to the delegate scrollview for zoom. I went to those conclusions testing on device and sim:
-The memory impact and footprint is exactly the same, even during zooming scrolling operation and it doesn't surprise me at all, the image is decompressed in memory
-Time profile say that a tileview take more time to be drawn during scrolling zoom operation instead of a uiimageview and that doesn't surprise me at all again the uiimageview is already drawn
-If I send memory warning nothing change between the two solution(only on sim)
-Testing Core Animation performance I get the same results around 60FPS
So what's the deal between those two views/layers why should I pick one instead of the other in these specific case? UIImageView seems to win the battle.
I hope that someone could help me to understand that.
They might perform the same for small images because ghen the only difference in terms os performance is that CATiledLayer draws on a background thread. Depending on the tile size CATiledLayer would even be slower because it has to draw multiple tiles for one image.
BUT ...
the point of CATiledLayer is that you don't need to draw all tiles, especially when zooming into a very very large image. It is smart to know which parts are actually needed. It also is smart about evicting tiles that are not needed any more.
Or this mechanism to work you need to provide the individual parts of the image separately. We're talking a total size of an image that probably cannot be held in memory uncompressed.

Resources