Very long restore time on my App - ios

I'm not sure what can be done about this. My app is an iPad app and I use about 300MB of ram. There are about 250MB of textures loaded for the game at any given time.
Here is the problem. When I sleep my iPad, if I sleep it for a few minutes and return to my game, it becomes playable again in seconds. If I leave my iPad sleeping after having played my game or while my game is still running for about 1 day then I go back, my game takes about 3.5 minutes to restore. It's not a bug, I've looked through the debugger many times and everything works as expected. iOS must be restoring the heap from somewhere which takes about 10 times longer than loading the game in from scratch.
My current solution is to forget about restoring and I intentionally crash my app so it restarts itself after it has been away which gets me to the same state about 10 times faster. But I don't like this solution.
Has anyone else experienced such issues? Are there api's I should be calling or something to lower the restore times after several hours of iPad sleeping? Is this issue documented anywhere?

My current solution is to forget about restoring and I intentionally
crash my app so it restarts itself after it has been away which gets
me to the same state about 10 times faster. But I don't like this
solution.
This is a guaranteed way to make sure that your app doesn't get approved for distribution on the App Store. There's two solutions to this problem:
1) Redesign your game. There's various techniques to this, including:
Breaking down levels into smaller pieces, so each stage requires less assets to load.
Shrinking textures and assets. E.g., use 256x256 textures instead of 512x512. One 512x512 texture takes up the space of four 256x256 textures. Would you rather load four of your textures in a scene in a few seconds, or 1?
Compress your textures. Compressed textures are smaller and quicker to load than their uncompressed bretheren.
Your application won't even run on an original iPad Mini, because of it's RAM - it has 512MB, and you're currently trying to use 300MB at any given time.
2) Disable your app from staying in the background.
Every time your app loses focus (besides lock screen being toggled), it'll force itself to be reloaded from scratch... much like you're already doing now with a forced crash. See:
If you never want your app to enter the background set the
UIApplicationExitsOnSuspend key in your application’s Info.plist file
to YES
How to exit app while enter background
Those are my suggestions, though in all honesty I'd do the first one if at all possible. It's more work, but you'd be able to make a more courteous iOS application when it comes to memory management plus you'd be able to target more devices.

Related

Preloading assets in AR with SceneKit

In our AR app and appclip made with SceneKit, we experience very significant drops in framerate when we make our 3D content appear at different steps of the experience. We have conducted our tests on an iPhone X (iOS 15.2.1), on an iPhone 12 Pro (iOS 14), and on an iPad Pro 2020 (iPad OS 14.8.1).
For now, all of our 3D objects are in our Main Scene. Those which are supposed to appear at some point in the experience have their opacity set to 0.01 at the beginning and then fade in with a SCNAction (the reason why we tried setting their opacity to 0.01 at the start was to make sure that these objects are rendered from the start of the experience).
However, if the objects all have their opacity set to 1 from the start of the experience, we do not experience any fps drop.
It is worth noting that the fps drops only happen the first time the app is opened. If I close it and re-open it, then it unfolds without any freeze.
What would be the best way to load (or pre-load) these 3D elements to avoid these freezes?
I have been told the prepareObject:shouldAbortBlock: and the prepareObjects:withCompletionHandler methods could solve our problem.
In our case the SceneView is an ARCNView, so we can't seem to access the SCNSceneRenderer methods. We have only managed to implement the "Prepare" method to preload our assets:
https://developer.apple.com/documentation/scenekit/scnscenerenderer/1523375-prepare
It seems to be doing something because we get a significantly longer freeze at the start of the experience, however, we still experience the same fps drops during the experience when our objects appear for the first time.
Is there any documentation on how to use the prepareObject:shouldAbortBlock: and the prepareObjects:withCompletionHandler methods in an ARCNView?

SceneKit scenes lag when resuming app

In my app, I have several simple scenes (a single 80 segment sphere with a 500px by 1000px texture, rotating once a minute) displaying at once. When I open the app, everything goes smoothly. I get constant 120fps with less than 50mb of memory usage and around 30% cpu usage.
However, if I minimize the app and come back to it a minute later, or just stop interacting with the app for a while, the scenes all lag terribly and get around 4 fps, despite Xcode reporting 30fps, normal memory usage, and super low (~3%) cpu usage.
I get this behavior when testing on a real iPhone 7 iOS 10.3.1, and I'm not sure if this behavior exists on other devices or the emulator.
Here is a sample project I pulled together to demonstrate this issue. (link here) Am I doing something wrong here? How can I make the scenes wake up and resume using as much cpu as they need to maintain good fps?
I won't probably answer the question you've asked directly, but can give you some points to think about.
I launched you demo app on my iPod 6-th gen (64-bit), iOS 10.3.1 and it lags from the very beginning up to about a minute with FPS 2-3. Then after some time it starts to spin smoothly. The same after going background-foreground. It can be explained with some caching of textures.
I resized one of the SCNView's so that it fits the screen, other views stayed behind. Set v4.showsStatistics = true
And here what I got
as you can see Metal flush takes about 18.3 ms for one frame and its only for one SCNView.
According to this answer on Stackoverflow
So, if my interpretation is correct, that would mean that "Metal
flush" measures the time the CPU spends waiting on video memory to
free up so it can push more data and request operations to the GPU.
So we might suspect that problem is in 4 different SCNViews working with GPU simultaneously.
Let's check it. Comparing to the 2-nd point, I've deleted 3 SCNViews behind and put 3 planets from those views to the front one. So that one SCNView has 4 planets at once. And here is the screenshot
and as you can see Metal flush takes up to 5 ms and its from the beginning and everything goes smoothly. Also you may notice that amount of triangles (top right icon) is four times as many as what we can see on the first screenshot.
To sum up, just try to combine all SCNNodes on one SCNView and possibly you'll get a speed up.
So, I finally figured out a partially functional solution, even though its not what I thought it would be.
The first thing I tried was to keep all the nodes in a single global scene as suggested by Sander's answer and set the delegate on one of the SCNViews as suggested in the second answer to this question. Maybe this used to work or it worked in a different context, but it didn't work for me.
How Sander ended up helping me was the use of the performance statistics, which I didn't know existed. I enabled them for one of my scenes, and something stood out to me about performance:
In the first few seconds of running, before the app gets dramatic frame drops, the performance display read 240fps. "Why was this?", I thought. Who would need 240 fps on a mobile phone with a 60hz display, especially when the SceneKit default is 60. Then it hit me: 60 * 4 = 240.
What I guess was happening is that each update in a single scene triggered a "metal flush", meaning that each scene was being flushed 240 times per second. I would guess that this fills the gpu buffer (or memory? I have no idea) slowly, and eventually SceneKit needs to start clearing it out, and 240 fps across 4 views is simply too much for it to keep up with. (which explains why it initially gets good performance before dropping completely.).
My solution (and this is why I said "partial solution"), was to set the preferedFramesPerSecond for each SceneView to 15, for a total of 60 (I can also get away with 30 on my phone, but I'm not sure if this holds up on weaker devices). Unfortunately 15fps is noticeably choppy, but way better than the terrible performance I was getting originally.
Maybe in the future Apple will enable unique refreshes per SceneView.
TL;DR: set preferredFramesPerSecond to sum to 60 over all of your SceneViews.

iOS games with random frame drops (including my game)

I'm almost finishing my iOS game written in Swift + SpriteKit.
It's a quite simple game, 30-32 nodes at max. Only 1 thing has physics. The rest is a few animated clouds (around 6). The CPU usage is around 2-3% and max RAM usage of 75-80MB.
Including that I also get frame drops when changing from one scene to another. Why that could be?
(I'm pre-loading all the textures and sounds during game init, and not on the scenes)
When I use the simulator for 5S up to 6S Plus, I don't see any frame drop in there. So that's weird. Looks like it's not my game but my iPhone 6S?
Now, I do also have other games installed on the same device from different developers, and I frequently get random frame drops too. Lags for 2-3 seconds and then comes back to 60fps.
Does anyone know if this is something that's happening after an X iOS update ? or I was even thinking this my be some kind of background service running that's killing my phone. Call it facebook, whatsapp, messenger, etc.
Is there any way I could possibly check on what's going on?
Was this caused by the way that newer versions of SpriteKit are defaulting to Metal render mode as compared to OpenGL mode? For example, do your problems go away when PrefersOpenGL=YES is added to Info.plist? I covered a bit of this performance issue in my blog post about a SpriteKit repeat shader. Note that you should only be testing on an actual iOS device, not the simulator.

Making Overall App Size Smaller

I just recently talked to an app marketing agency and they are strongly recommending that I find a way to take my 153MB app and somehow get it under the 50MB mark that is the current standard for downloading over a wireless network (3G, 4G, etc.).
I have no idea where to go from here. As far as app size goes, my app is very UI intensive and I have a combination of (mostly) JPGs, PNG's, and a few small videos. I've already run all my jpg's through JPEGmini and as many png's as still looked alright through tinypng.org.
I'm curious if I could somehow "compress" or zip my resources and then unzip them in code to significantly reduce my app size (Before it's installed on the device...I don't care how big it expands to after it's downloaded and installed).
Host the video somewhere else and then downloading them after the app starts for the 1st time (or when they are actually played) maybe the biggest win. Other small wins would be drawing procedurally as oppose to using images. What is the combined size of your images, also the combined size of your videos?

performance issues with air app on iphone 4

Currently I am working on an Air app for iOS and Android. Air 3.5 is targeted.
Performance on iPhone 4 / 4s has been acceptable overall, after a lot of optimising: gpu rendering, StageQuality.LOW, avoiding vectors as much as possible etc. I really put a lot of effort in boosting performance.
Still, every once in a while, the app becomes very slow. There is no precise point in time or action or combination of actions after which this occurs. Sometimes, it doesn't occur for days. But when it occurs, only killing the app and launching it again helps, because the app stays slow after that. So I am not talking about minor hiccups that
The problem occurs only on (some) iPhones 4 and 4s. Not on iPad 3,4, iPhone 5, any Android device...
Has anyone had similar experiences and pointers as to where a solution might be found?
What happens when gpu memory fills up? Or device memory? Could this be involved?
Please don't expect Adobe Air to have performance as Native Apps. I am developing App with Adobe Air as well.
By the sound of your development experience. I think it's to do with memory issue, because the performance is not too bad at the begging stage, but it gets bad overtime (so u have to kill the app). I suggest you looking into memory leaking issue.
Hopefully my experience can help you.
I had a similar problem where sometime during gameplay the framerate would drop from 30fps to an unrecoverable 12fps. At first I thought I was running out of GPU memory and it was falling back on rendering with CPU.
Using Adobe Scout I found that when this occurred, the rendering time was ridiculousness high.
Updating to Air 3.8, I fixed the problem by limiting the amount of bitmaps that were being rendered and in memory at once. I would only create new instances of backgrounds for appropriate levels, and then flagging them for garbage collection when the level ended, waiting a few seconds and then moving to the next level.
What might solve your problem is if you reduce the amount of textures you have in memory at one time, only showing the ones you need to. If you want to swap out active textures for new ones, set all the objects with that texture data to null:
testMovieClip = null;
and remove all listeners from it so that garbage collection will pick it up.
Next, you can force garbage collection with AIR:
System.gc();
Instantiate the new texture you want to render a few frames after calling gc. Monitor resources with Scout and the iOS companion app to confirm that it's working.
You could also try to detect when the framerate drops, and set some objects to null then force garbage collection. In my case, if I moved my game to an empty frame for a few seconds with garbage collection, the framerate would recover and the game would resume rendering with GPU.
Hope this helps!

Resources