I load a table view, and I'm performing no activity intentionally
except letting the table view show, I'll wait a few seconds and then
my CPU usage shoots up. How can I find the cause?
Instruments says around 3% of CPU time goes to cellForRowAtIndex method, with that one being the most consuming method. Of that 3%, 75% goes.
It's dependent to RAM and device memory.... I have to manage according to device .
Check what happens on the simulator. If the simulator uses hundred percent, it's a bug in your code. If the simulator uses say 20-30%, it might be your app has lots of work to do.
Simplest way is trying to press "pause" in the debugger and see what code is executing... If your app takes 100% and you think it should do nothing, chances are that pressing pause will stop right in the code that shouldn't be running.
Related
There are a couple of games that I want to mention, to show how they handle entering the background mode:
Clash of Clans. It seems it doesn't free any memory at all when it enters background mode, in fact I can open lightweight applications like Notes and get back to the game to continue playing without any noticeable delay, which seems pretty cool to me from the user's perspective.
Game of War. The game immediately falls back to the loading screen and the initialization process starts all over again when it runs inmediately after it enters background mode, it's just like restarting the game, which is very annoying sometimes.
So, in the case of my game, it has an average memory footprint of 25 mb (and it's going to be less with some optimisations), I know the "Free up as much memory as possible" stuff recommended in order to be a good neighbour on the iOS platform, but considering that freeing memory when the game enters background mode could cause my game to have an "annoying" pause when it enters foreground mode...
...should I save the progress and pause the game when entering background mode without freeing up any memory at all, or should I free as much memory as possible and load those resources again when entering foreground mode, with the respective loading pause?
As you yourself point out (by giving two games as examples that use opposite strategies), there is no unique answer to your question.
I think a proper answer can be worked out in a given case by clearly defining the use cases you want your app to support.
E.g., one use case, as you mention, could be "the user can switch to a lightweight app and go back to the game without unnecessary waits". (UC1) Then, you should also have a list of lightweight apps and reference devices where you want to make sure that the use case is actually satisfied.
On the other hand, you may want to support a slightly different use case: "the user will always come back to the point where she left the game, unless the app was terminated, in which case the app should present the main menu". (UC2)
In the first case, not freeing up could be the best approach; in the second case, you may want to minimise the chance that the app is terminated while the user does another task (lightweight or not), so that she can go back to the place where she left, even though she has to wait for all resources to load.
There might even be cases where an intermediate approach is best, where you free up only a part of memory, so to strike a balance.
And, of course, it would make no sense going for the first use case (UC1) if your app memory footprint is so large that it will be terminated almost immediately after switching to another app on most of the devices. In such case, it might make more sense freeing up memory, so you at least can spare the app load time (vs. resources load time) when you go back to it.
So, in the end, it depends...
I would save the progress and pause the game when entering the background without freeing up memory, as many people if they need the memory just delete it from the history thing, or the "carousel of cards". Multi tasking is emphasized in ios 7 so you don't want them to restart the game.
for example, somebody wants to text someone in the middle of playing your game. They exit the game and text someone. But then they have to load the game again. Nobody likes this.
While your game doesn't take up much memory, most users don't bother to close out of applications. I would recommend freeing up as much memory as possible without sending them back to the start menu, much like #sergio recommended with his 'intermediate' option.
I strongly suggest to free up memory. I have an iPhone 4, and some apps are now taking too much persistent memory, so that switching between them becomes a nightmare. E.g. recently, I could not switch between Safari and Twitter anymore, without them reloading all their state (taking more than 20 seconds in both directions).
Bottom line: Try to keep important state, but with as little memory as possible (i.e. not retaining images / textures), otherwise the app will get closed on older devices and you will effectively lose more state.
Save the progress and free the memory with the loading pause, especially if your game is for older devices. I have an iPhone 4, and when a game is running in the background without freeing memory, my foreground apps crash every 15 minutes. But if you have things such as "Vehicle/weapon upgrade is done in x minutes", you will need to save game progress and free the memory, so only the upgrade timer is running. If you do enough optimisations you may decrease the memory footprint, so I would recommend you to keep the optimisations in mind while coding and then the background performance will be your least problem.
While attempting to optimize load speed I started placing timers in different places and looking at the performance. The app uses OpenGL and Core Data and has a decent amount of screens and artwork.
But the largest part of the lag seems to be taking place prior to applicationWillEnterForeground (assuming it's not a cold load)
The app shows up and is displayed and the UI is unresponsive for close to 5 seconds. I start a timer and print a time as soon as I can press a button. The time between applicationWillEnterForeground and when I can press the button is 200 milliseconds.
What can be causing my application to be slow to load prior to applicationWillEnterForeground or what can I do evaluate what is happening there? Instruments does not seem to display any information about that part of the launch.
Other testing app I have don't seem the same performance. Is it the bundle size or the amount of memory used by the application? Loading dynamic libraries?
This was related to OpenAL. The app was not closing the OpenAL context and for some reason this caused considerable problems when closing and reloading the app. The app uses CosCos Denshion so I to make sure to call these.
[CDAudioManager end];
[SimpleAudioEngine end];
I have this iPhone app created in Cocos2d 2.1.
WHen the app first starts it presents a full screen background and a UIACtionSheet where the user has to choose one option to start the application. That's it. This actionsheet is presented by the first scene to run by the delegate (HelloWorldLayer scene).
Nothing else is loaded. Nothing is running on any thread that I am responsible for that. Even so, the CPU usage is about 20%. I have profiled that on instruments and this is what I have:
I see this [CCGLView swapBuffers] that is inside something that calls attention, ths CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION (CoreFoundation).
If I choose "show obj-c only" I see this:
Apparently the guilty is this drawScene but how can a scene with a background image and a UIActionsheet use that much CPU?
How do I trace the source of this problem?
NOTE. This is being tested on the device. On simulator CPU usage is 77%!!!!!
Cocos2d, like any OpenGL application, redraws the contents of the screen every frame. Typically that means 60 frames per second. Swapping the frame buffers and all the other overhead associated takes some CPU time.
So what you're observing is normal behavior, there's nothing that can be done about it. There is no concept of "idle" in a rendering engine, it draws the contents of the screen even if they didn't change (or the screen is empty) on the assumption that screen contents usually do change.
You can however pause the CCDirector to reduce framerate, conserving CPU cycles and battery. Or call stopAnimation to completely stop all updates, including scheduled selectors. However what happens to the framebuffer is undefined, usually it sticks around (ie the last rendered frame "freezes") but this may not be true for all situations and devices.
As far as Simulator is concerned: ignore it. Its performance characteristics are not the least bit comparable nor instructive.
I don't have any hardcore data supporting this, but generally, you'll notice that any app you play with or one you're working on, when the app first loads, doing something such as displaying a modal view controller is slow the first time, but every subsequent time, it's really fast. For my app, when I present a modal view controller the first time, it takes about 3 seconds, but if I do it over and over again after that, it takes less than a second every time. What is the reason for this?
There's a bunch of possible explanations here.
Something's been cached. The first time, it had to load something from "disk," the second time it was already in memory. This could be an entire framework, or NIBs or graphic resources in the OS itself.
Memory management. iOS didn't have enough memory to satisfy the request the first time. iOS spent some time clearing out memory, possibly quitting background applications. The second time, it's already available.
Probably many others.
Caching. Off the top of my head, images are often cached, and I wouldn't be surprised if the nib was cached as well.
No, I don't notice this in my app. The cause of what you are seeing could be a hundred different things, so we need a bit more data to make an informed answer.
Suggest you run Instruments, narrow down the time window to the initial 3-second pause, then see what the machine is doing during that time. Run it multiple times and look at CPU, IO, memory, anything that could be slowing it down.
I'm looking for help with a very specific memory-management issue where didReceiveMemoryWarning doesn't appear to be getting called in cases where it should be.
I have a straightforward app that's a story with pages. I have an outer view/controller that manages the page views/controller. Each page view has a picture on it of decent size (200-300k). It's large because it's a universal app, so they're all 1024x768, then get scaled down for the iPhone. I have implemented didReceiveMemoryWarning to release unused controllers (whatever's not showing at the time). The app works fine when didReceiveMemoryWarning gets called, but it does not always get called. On the iPod Touch 2G, if I'm going from page to page fast, it will often just kill the program without calling didReceiveMemoryWarning (I put a breakpoint there to see). On an iPhone 1G which has the same amount of RAM, didReceiveMemoryWarning gets called at reasonable times and I never run out of memory.
The log prints "Received memory warning level 1/2" as expected right before my code does get called, but I don't see it in the logs in the iPod Touch 2G when my app gets killed without a chance to free up memory.
I've used static analysis and the leaks tool and the memory profile looks good. I don't think leaks have anything to do with the problem. Rather, the problem is that my program doesn't get the opportunity to free up resources when memory is tight. I do want to keep unseen pages in memory when there's enough memory - it allows for quick paging and makes the pan gesture for changing pages work responsively.
Has anyone else seen this? If anyone has hints, I'd appreciate it. I'm also curious if anyone knows under what conditions didReceiveMemoryWarning should get called. Is it possible that my program is gobbling up so much memory so fast that iOS doesn't have an opportunity to free up memory?
Memory warnings appear to come too late when allocating a lot of memory "too" quickly, especially if the app doesn't spend enough idle time in the run loop between allocations.
Try preflighting (attempt to allocate and then release) memory, and return to the run loop, maybe a half second before you really need the memory.