Memory warnings in Cocos2d/Box2d apps on device (iPhone/iPad) - cocos2d-iphone

Here's the info of profile->leaks in Xcode and I ran it on iPad 2 for about 21 mins 12 seconds before crashing.
live Bytes ---- 5.45 MB
Living ---- 13547
Transitory ---- 3845036
overall Bytes -- 720.31 MB
When the app is running on device, the app crashes printing Received Memory Warning in Console.
I'm not very sure of how it works.
But please tell me if an app runs for 21 minutes on a device, uses an overall of around 720 MB memory in total during this run, yet live bytes never go beyond 7.0 MB.
I accept that the app starts by using 3.25 MB as live bytes & it goes to 5.45 MB on live bytes during this run & I'm not pretty sure how live bytes go on increasing like this.
But my question is:
Is it an app bad enough to produce crashes while running on device?
Or
Am I facing some other problem?

You probably are leaving tons of sprites in the CCTextureCache singleton. Everytime you create a CCSprite, the texture is cached (silently) so that the next time you refer to it, the loading and presentation will be faster (much faster). Run the allocations profiling in simulator (see two pics below):
and
The top image is from allocations profiling on device. Max memory 4.4 Mb.
The bottom image is the same app, the SAME gameplay sequence, while profiling in the simulator (peaks at around 78 Mb). By running in simulator, i can see in the allocations the memory used by my sprites. In the device, this memory is not accounted for by the allocations tool.
You are looking for trends and discrete big jumps. If you never come back down, you are probably leaving behind unused sprites. In my case, i choose to free specific resources from the textures at specific point in the game's execution. Here is an example from the appController
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
MPLOGERROR(#"Before purge");
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
[CCAnimationCache purgeSharedAnimationCache];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCDirector sharedDirector] purgeCachedData];
MPLOGERROR(#"%After purge");
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
}
This is last ditch, brute force cleanout. But you can remove specific textures at different point during game play without impacting the 'perceived' responsiveness of the app. Caches are generally sound in principle, but can become rapidly tricky in the face of constrained resources. Learn about it, experiment, and eventually you will find the right mix of 'what stays/what goes' for smooth application performance.
ps. although the simulator is fine for certain tests, dont use its 'performance' as a benchmark. Simulator performance is meaningless when it comes to graphics, it does not use your computer's GPU (and that is why you see the graphic memory allocation :) ).

Related

Game gets slow if after playing 5-6 times in Cocos2d-iphone

This is a new type of problem i am facing in my game . I can say that i have implemented all the code for the Game . But i am facing problem with it. Actually what happen is when i play it for more than 5-6 times then game gets slower , means we can feel that it's going on slow. But it's FPS is 60 but the fluctuation in FPS takes place between 60 to 30.
In my game I've implemented ARC. I also can see that every time number of object that are present in the scene are same.
I have also used instruments to check memory leak in the game but there is no memory leak in game. I can't show the code because its confidential.
But I couldn't be able to solve this problem. I would like to know what can be the reason behind this and How can i solve this issue.
Any kind of help can be helpful
Although I dont use the Apple toys to do this, i perform a heapshot-like analysis every time i run my apps : the facility to do that are built-in to every one of my classes, to enable me to determine exactly the number of instances currently allocated (not deallocated) at any point during program execution. It is a bit of work (say approximately 1 minute) per class when I add one to a project, but a life saver over the life of the project.
Coming back to your question above in the comments, no i have no clue about your 500K. The only person that can figure that out at this moment is you. If your game has a logical point (like a game main menu) where you can come back before quitting the app (i mean hard kill), at that place I would start by doing this, just after the menu is drawn :
// below code with cocos2d 2.x
NSLog(#"*** before purge ***");
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
[CCAnimationCache purgeSharedAnimationCache];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCDirector sharedDirector] purgeCachedData];
[self scheduleOnce:#selector(dumpTextures) delay:0.5f];
// let the run loop cycle a bit
// to give a chance for auto-release objects to be
// disposed from the pool ...
-(void) dumpTextures {
NSLog(#"*** after purge ***");
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
}
and examine the result. Look for any texture that is cocos2d is still holding for you ... the most likely memory hog by far. I dont think that 5-6 times 500K would make much of a difference in a game that peaks around 140Mb.
There is a difference between leaking memory and abandoning memory. ARC helps with the leaks but it still allows you to retain strong references to your objects when they are no longer needed. An example of this is retain cycles.
You can perform a technique known as Heapshot Analysis. Using instruments it will show you what memory is being retained when it doesn't need to be anymore after a game has finished.
There is a tutorial on Heapshot here. http://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode

Should I just scale small images to other form factors in a cocos2d game?

I have a universal iOS game built with cocos2d-iphone that has a large number of small images (amongst others). For these small images, the game works fine with a 1:2:4 ratio for iphone:ipad/iphone-retina:ipad-retina. I have two approaches to enable this in the game:
A) Have three sets of sprites/spritesheets - for the three form factors required and name them appropriately and have the images picked up
B) Have one set of highest resolution images that are then scaled depending on the device and its resolution aSprite.scale=[self getScaleAccordingToDevice];
Option A has the advantage of lesser runtime overhead at the cost of high on disk footprint (an important consideration, as the app is currently ~94 MB).
Option B has the advantage of a smaller on disk footprint, but the cost is that ipad retina images will be loaded in memory even for the iphone 3gs (lowest supported device).
Can someone provide arguments that will help me decide one way or the other?
Thanks
There is no argument: use option A.
Option B is absolutely out of the question because you would be loading images that may be 6-8 times larger in memory (as a texture) on a device (3GS) that has a quarter of the memory of an iPad 3 or 4 (256 MB vs 1 GB). Not to mention the additional processing power needed to render a scaled down version of such a large image. There's a good chance it won't work at all due to running out of memory and running too slowly (have you tried?).
Next, it stands to reason that at 95 MB you might still not get your app below 50 MB with option B. The large Retina textures make up two thirds or three quarters of your bundle size , the SD textures don't weigh in much. This is the only app bundle size target you should ever consider because below 50 MB users can download your app over the air, at over 50 MB they'll have to sync via Wifi or connected to a computer. If you can't get below 50 MB, it really doesn't matter if your bundle size is 55 MB or 155 MB.
Finally there are better options to decrease bundle size. Read my article and especially the second part.
If your images are PNG the first thing you should try is to convert them all to .pvr.ccz and as NPOT texture atlases (easiest way to do that: TexturePacker). You may be able to cut down bundle size by as much as 30-50% without losing image quality. And if you can afford to lose some image quality there are even greater savings possible (plus additional loading and performance improvements).
Well, at 94Mb, your app is already way beyond the download limit for phone network, ie it will only ever be downloaded when some internet connection is available. So ... is it really an issue? The other big factor you need to consider is memory footprint when running. If you run 4x on a 3G and scale down, the memory requirement will still be for the full size sprite (ie 16x the amount of memory :). So the other question you have to ask yourself is whether that game is likely to 'run' with a high memory foot print on older devices. Also, the load time for the textures could be enough to affect the usability of your app on older devices. You need to measure these things and decide based on some hard data (unfortunately).
The first test you need to do is to see whether your 'scaled down' sprites will look ok on standard resolution iphones. Scaling down sometimes falls short of expectations when rendered. If your graphic designer turns option B down, you dont have a decision. He/she has the onus of providing all 3 formats. After that, if option B is still an option, I would start with option B, and measure on 3GS (small scale project, not the complete implementation). If all is well, you are done.
ps : for app size, consider using .pvr.ccz formats ( I use texture packer). Smaller textures and much faster load time (because of the pvr format). The load time improvement may be smaller on 3GS because of generally slower processor - need to un compress.

C++/opengl application running smoother with debugger attached

Have you experienced a situation, where C++ opengl application is running faster and smoother when executed from visual studio? When executed normally, without debugger, I get lower framerate, 50 instead of 80, and a strange lagging, where fps is diving to about 25 frames/sec every 20-30th frame. Is there a way to fix this?
Edit:
Also we are using quite many display lists (created with glNewList). And increasing the number of display lists seem to increase lagging.
Edit:
The problem seems to be caused by page faults. Adjusting process working set with SetProcessWorkingSetSizeEx() doesn't help.
Edit:
With some large models the problem is easy to spot with procexp-utility's GPU-memory usage. Memory usage is very unstable when there are many glCallList-calls per frame. No new geometry is added, no textures loaded, but gpu-memory-allocation fluctuates +-20 Mbytes. After a while it becomes even worse, and may allocate something like 150Mb in one go.
I believe that what you are seeing is the debugger locking some pages so they couldn't be swapped to be immediately accessible to the debugger. This brings some caveats for OS at the time of process switching and is, in general, not reccommended.
You will probably not like to hear me saying this, but there is no good way to fix this, even if you do.
Use VBOs, or at least vertex arrays, those can be expected to be optimized much better in the driver (let's face it - display lists are getting obsolete). Display lists can be easily wrapped to generate vertex buffers so only a little of the old code needs to be modified. Also, you can use "bindless graphics" which was designed to avoid page faults in the driver (GL_EXT_direct_state_access).
Do you have an nVidia graphics card by any chance? nVidia OpenGL appears to use a different implementation when attached to the debugger. For me, the non-debugger version is leaking memory at up to 1 MB/sec in certain situations where I draw to the front buffer and don't call glClear each frame. The debugger version is absolutely fine.
I have no idea why it needs to allocate and (sometimes) deallocate so much memory for a scene that's not changing.
And I'm not using display lists.
It's probably the thread or process priority. Visual Studio might launch your process with a slightly higher priority to make sure the debugger is responsive. Try using SetPriorityClass() in your app's code:
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
The 'above normal' class just nudges it ahead of everything else with the 'normal' class. As the documentation says, don't slap on a super high priority or you can screw up the system's scheduler.
In an app running at 60 fps you only get 16ms to draw a frame (less at 80 fps!) - if it takes longer you drop the frame which can cause a small dip in framerate. If your app has the same priority as other apps, it's relatively likely another app could temporarily steal the CPU for some task and you drop a few frames or at least miss your 16 ms window for the current frame. The idea is boosting the priority slightly means Windows comes back to your app more often so it doesn't drop as many frames.

glDrawArray+VBO increasing memory footprint

I am writing a Windows based OpenGL viewer application.
I am using VBO + triangle strip + glDrawArrays method to render my meshes. Every thing is perfectly working on all machines.
In case of Windows Desktop with nVidia Quadro cards the working/peak working memory shoots when i first call glDrawArray.
While in case of laptops having nvidia mobile graphic cards the working memory or peak working memory does not shoot. Since last few days i am checking almost all forums/post/tuts about VBO memory issue. Tried all combinations of VBO like GL_STATIC_DRAW/DYNAMIC/STREAM, glMapbuffer/glunmapbuffer. But nothing stops shooting memory on my desktops.
I suspect that for VBO with ogl 1.5 i am missing some flags.
PS: I have almost 500 to 600 VBO's in my application. I am using array of structures ( i.e. v,n,c,t together in a structure). And I am not aligning my VBOs to 16k memory.
Can any one suggest me how I should go ahead to solve this issue. Any hints/pointers would be helpful.
Do you actually run out of memory or does your application increasingly consume memory? If not, why bother? If the OpenGL implementation keeps a working copy for itself, then this is probably for a reason. Also there's little you can do on the OpenGL side to avoid this, since it's entirely up to the driver how it manages its stuff. I think the best course of action, if you really want to keep the memory footprint low, is contacting NVidia, so that they can double check if this may be a bug in their drivers.

What can cause a reduction in frame rate when upgrading a graphics card?

We have a two-screen DirectX application that previously ran at a consistent 60 FPS (the monitors' sync rate) using a NVIDIA 8400GS (256MB). However, when we swapped out the card for one with 512 MB of RAM the frame rate struggles to get above 40 FPS. (It only gets this high because we're using triple-buffering.) The two cards are from the same manufacturer (PNY). All other things are equal, this is a Windows XP Embedded application and we started from a fresh image for each card. The driver version number is 169.21.
The application is all 2D. I.E. just a bunch of textured quads and a whole lot of pre-rendered graphics (hence the need to upgrade the card's memory). We also have compressed animations which the CPU decodes on the fly - this involves a texture lock. The locks take forever but I've also tried having a separate system memory texture for the CPU to update and then updating the rendered texture using the device's UpdateTexture method. No overall difference in performance.
Although I've read through every FAQ I can find on the internet about DirectX performance, this is still the first time I've worked on a DirectX project so any arcane bits of knowledge you have would be useful. :)
One other thing whilst I'm on the subject; when calling Present on the swap chains it seems DirectX waits for the present to complete regardless of the fact that I'm using D3DPRESENT_DONOTWAIT in both present parameters (PresentationInterval) and the flags of the call itself. Because this is a two-screen application this is a problem as the two monitors do not appear to be genlocked, I'm working around it by running the Present calls through a threadpool. What could the underlying cause of this be?
Are the cards exactly the same (both GeForce 8400GS), and only the memory size differ? Quite often with different memory sizes come slightly different clock rates (i.e. your card with more memory might use slower memory!).
So the first thing to check would be GPU core & memory clock rates, using something like GPU-Z.
It's an easy test to see if the surface lock is the problem, just comment out the texture update and see if the framerate returns to 60hz. Unfortunately, writing to a locked surface and updating the resource kills perfomance, always has. Are you using mipmaps with the textures? I know DX9 added automatic generation of mipmaps, could be taking up a lot of time to generate those. If your constantly locking the same resource each frame, you could also try creating a pool of textures, kinda like triple-buffering except with textures. You would let the render use one texture, and on the next update you pick the next available texture in the pool that's not being used in to render. Unless of course your memory constrained or your only making diffs to the animated texture.