I load my animated character with a huge texture this way:
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:#"MyFile.plist"];
And later, when I am no longer using the character, I release memory using:
[[CCSpriteFrameCache sharedSpriteFrameCache]removeSpriteFramesFromFile:#"MyFile.plist"];
And also:
[[CCTextureCache sharedTextureCache]removeTextureForKey:#"MyFile.png"];
Just to be sure.
I do that because the texture it uses consumes a lot of memory, so I make sure I dispose of it so my app doesn't crash. Is the above code correct?
Anyway, here is the actual problem: I eventually load my character again, and dispose of it again. Eventually, after a couple revives and kills, the app crashes. The log says nothing about it, so I can just suspect that it was due to memory - that's why I assumed that I wasn't disposing the texture properly.
I do need to create and dispose the character's texture. I can't afford to have it preloaded in the game.
I usually use the brute force approach as follows:
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
at specific moments in the game flow. It is not too too costly to have coco scan its arrays, in the grand scheme of things. As in your case, in my current game i must load and ditch. CCTextureCache has CCLOG'ing that permit you to witness whether the removal actually occurs when you expect it, or close to it (autorelease has its quirks). If not, you are probably retaining some handle to the texture somewhere, a sprite, batch node, an CCAnimation, or an action.
Did you also try purgeSharedTextureCache as noted here:
http://www.cocos2d-iphone.org/api-ref/0.99.0/interface_c_c_texture_cache.html#ac673f75cd5418bdcecf1fb8717a40345
You can see it in work also in your App Delegate methods that release textures during memory warnings.
Related
I am writing an SDL2 C++ program that creates clips from large sprite sheets and has a system loop to render them. So, only a few textures but many, many derivative clips. As I understand it, these are the facts
the advantage using clips is that copying a portion of the larger original texture is more efficient
loading the texture and clipping is best done before the system loop,
memory leaks prevention/trash cleanup dictates you destroy and recreate textures with every loop cycle,
after the loop ends, you should destroy everything: windows, renderer, and textures
Obliterating everything I understand. But how does the cyclical cleanup within the loop work with clips, and what should go before, within and after my loop? Am I supposed to be destroying and recreating all the clips once every cycle, every time I render present a new batch onscreen, or cleanup after each individual clip? Am I supposed to destroy the original textures as well and then recreate the clips?
I have spent a great deal of time trying to figure out OSG's memory management.
I have a scene graph with several children (actually a LOD based on an octree).
However, when I need to reset my scene (I just want to wipe ALL nodes from de scene and also wipe the memory), I use
// Clear main osg::Group root node
m_rootNode->removeChildren(0, m_rootNode->getNumChildren());
m_rootNode->dirtyBound();
// Clear Main view scene data from osg::Viewer
m_viewer->setSceneData(nullptr);
BEFORE I do this, I check all my nodes with a NodeVisitor pattern, and found out that ALL my nodes have reference count of 1, i.e, after clearing them from the scene, I expect my memory to be freed. However, this does not happen: my scene is actually reset, all the nodes disappear from the viewer, but the memory remains occupied.
Nonetheless, when I load another scene to my viewer, the memory is rewritten somehow (i.e., the memory usage does not increase, hence there is no memory leak, but used memory is always the same)
I can't have this behaviour, as I need to closely control memory usage. How can I do this?
Looks like OSG keeps cached instances of your data, either as CPU-side or GPU-side objects.
You could have a look at osgDB's options to disable caching in first place (CACHE_NONE, CACHE_ALL & ~CACHE_ARCHIVES), but this can actually increase your memory consumption as data may not be re-used and re-loaded multiple times.
You could instruct osg::Texture to free the CPU-side texture data after it was uploaded to OpenGL - in case you don't need it any more. This can be done conveniently via the osgUtil::Optimizer::TextureVisitor which you would want to set up to change the AutoUnref for each texture to true. I think, running osgUtil::Optimizer with the OPTIMIZE_TEXTURE_SETTINGS achieves the same effect.
Then, after closing down your scene, as you did in your Question's code, you could explicitly instruct OSG's database pager to wipe its caches:
for( osgViewer::View v in AllYourViews )
{
v->getDatabasePager()->cancel();
v->getDatabasePager()->clear();
}
To finally get rid of all pre-allocated GPU-side objects and their CPU-side representations, you would need to destroy your views and GLContext's.
I am getting crashes on iPhone 4s due to "memory pressure." My game is set up like this:
Main scene sprite sheet that always stays in memory.
Individual game scene levels load from individual textures (not sprite sheets).
When a level is done and we return to the main scene, I would like those cached game scene textures to get dumped. What ends up happening is that when you play through 3-4 levels, it crashes as it runs out of memory as it never releases this memory after a level. I don't want the level textures to be cached past the lifespan of the game scene. When returning to the main scene, it needs to release this memory.
I have tried removing all of the game scene children which does nothing to memory. I have tried looking for a specific way to clear just these textures I have loaded in this game scene from the cache.
Any suggestions?
Are you using cocos2d v2? You probably have memory leaks since unused textures are removed when necessary. Try profiling your app to see if you have leaks and where they are at.
You also can call these methods yourself at the appropriate time, although I doubt you'd have to:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
But again what you describe sounds more like memory leaks. When your application receives a memory warning the cached data is purged. During this purge the remove unused textures method is called on the texture cache, among other things. If you have 3/4 levels of data still lurking around long after you've exited those scenes, that sounds like a memory leak.
I'm assuming this only happens after visiting multiple scenes and the problem just isn't that your 4th scene is simply trying to load more data than the device can handle.
You can remove specific textures calling:
In cocos2D-x v3.x :
Director::getInstance()->getTextureCache()->removeTextureForKey(ImageKeyName)
In cocos2D-x v2.x :
CCTextureCache::sharedTextureCache()->removeTextureForKey(ImageKeyName);
Where ImageKeyName is just the path of the image (the same you used to load the texture)
I developed a game with SDL2.00 and c++. I seemed to be having memory and CPU issues. CPU usage goes up to 40% and memory usage goes up by 5mg a second.
So I think the reason is the way Im handling Textures\Sprites.
My question is should I create a different/new sprite/texture for every instance ?
For example, I have a class called Enemy which contains all the variable and methods related to enemy monsters such as HP, damage, location , image(Texture) etc. This class contains its own texture to be rendered onto the renderer.
Is this the right way? Or should I create a Sprite/Texture for all the images before hand and render them as needed?
and I'm wondering if this will render two different images onto the renderer:
RenderCopy(renderer, image);
image->SetPosition(X,Y);
RenderCopy(renderer,image);
or is it going to move the sprite to the new position?
I think my issues are caused my overloading the renderer and/or having too many textures being loaded.
Let me know what you think .
OpenGL is not a scene graph. It's a drawing API. So everytime you're allocating a new texture you're creating a new data object that consumes memory. You should reuse and share resources where possible.
My question is should I create a different/new sprite/texture for
every instance ?
No, not unless every instance of the sprite uses different textures, otherwise you should reuse them, ie only load them once and store a pointer to the texture the sprite uses.
and I'm wondering if this will render two different images onto the
renderer:
RenderCopy(renderer, image);
image->SetPosition(X,Y);
RenderCopy(renderer,image);
or is it going to move the sprite to the new position?
This will copy the image twice. First at the old position and then at the new. What you will get is a trailing image. You should probably either clear the previous position or render the background at that position (or whatever should be there).
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