Memory Issues on iOS

Discussion of issues specific to mobile platforms such as iOS, Android, Symbian and Meego.
Post Reply
Carlyone
Kobold
Posts: 38
Joined: Thu Jul 05, 2012 3:51 pm

Memory Issues on iOS

Post by Carlyone » Thu Mar 14, 2013 12:05 pm

Hello,
We've been developing a combined AR / Viewer application, using Ogre as our engine. Some of the models we have been given to fit in are quite large and the images are quite large as well. Ogre does load these but the cleanup doesn't seem to release the memory, even though the managers report that the mesh is unloaded etc.

In a simple example I took the Ogre iOS template, loaded the ogrehead.mesh then unloaded it.

Ogre on startup (with skybox, camera, light) sits at 1.54MB, after loading the ogrehead.mesh and displaying it on screen it is at 1.95MB and after running all of the unload code I can find it is at 1.91MB. I would be hoping to get it a lot closer, even exactly, back at 1.54MB

Below is the creation code:

Code: Select all

Ogre::Entity* m_pCubeEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity("Cube", "ogrehead.mesh");
Ogre::SceneNode* m_pCubeNode = OgreFramework::getSingletonPtr()->m_pSceneMgr->getRootSceneNode()->createChildSceneNode("CubeNode");
m_pCubeNode->attachObject(m_pCubeEntity);
Below is the removal code:

Code: Select all

Ogre::MeshManager::getSingleton().unload("ogrehead.mesh");
Ogre::MeshManager::getSingleton().remove("ogrehead.mesh");
        
//Cleanup the node
Ogre::SceneNode* node = OgreFramework::getSingletonPtr()->m_pSceneMgr->getSceneNode("CubeNode");
        
Ogre::SceneNode::ObjectIterator objIter = node->getAttachedObjectIterator();
while(objIter.hasMoreElements()){
    Ogre::MovableObject * obj = objIter.getNext();
    node->detachObject(obj);
            
    if(OgreFramework::getSingletonPtr()->m_pSceneMgr->hasManualObject(obj->getName())){
        OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyManualObject(obj->getName());
    }
    OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyMovableObject(obj);
            
     obj = NULL;            
}
node->removeAndDestroyAllChildren();
        
OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyEntity("Cube");
OgreFramework::getSingletonPtr()->m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(node->getName());
        
node = NULL;
        
// Clear the materials
        
Ogre::MaterialManager::getSingleton().unload("Ogre/Earring");
Ogre::MaterialManager::getSingleton().remove("Ogre/Earring");
        
Ogre::MaterialManager::getSingleton().unload("Ogre/Skin");
Ogre::MaterialManager::getSingleton().remove("Ogre/Skin");
        
Ogre::MaterialManager::getSingleton().unload("Ogre/Tusks");
Ogre::MaterialManager::getSingleton().remove("Ogre/Tusks");
        
Ogre::MaterialManager::getSingleton().unload("Ogre/Eyes");
Ogre::MaterialManager::getSingleton().remove("Ogre/Eyes");
        
// Clear the materials
Ogre::TextureManager::getSingleton().unload("GreenSkin.jpg");
Ogre::TextureManager::getSingleton().remove("GreenSkin.jpg");
        
Ogre::TextureManager::getSingleton().unload("spheremap.png");
Ogre::TextureManager::getSingleton().remove("spheremap.png");
        
Ogre::TextureManager::getSingleton().unload("tusk.jpg");
Ogre::TextureManager::getSingleton().remove("tusk.jpg");
        
// Remove any unused resources
Ogre::MeshManager::getSingleton().removeUnreferencedResources();
Ogre::TextureManager::getSingleton().removeUnreferencedResources();
Ogre::MaterialManager::getSingleton().removeUnreferencedResources();
Am I missing a call or am I missing the idea entirely on clearing memory from Ogre?

I have read a few posts that reference the MemoryTracker but I haven't seen any examples of it's use. Also will I need to rebuild ogre from source (as opposed to using the pre-packaged sdk) to get it?

Any help on this would be greatly appreciated

Carl
Last edited by Carlyone on Thu Mar 14, 2013 3:51 pm, edited 1 time in total.
0 x

User avatar
masterfalcon
OGRE Team Member
OGRE Team Member
Posts: 4270
Joined: Sun Feb 25, 2007 4:56 am
Location: Bloomington, MN
Contact:

Re: Memory Issues on iOS

Post by masterfalcon » Thu Mar 14, 2013 3:38 pm

Just at a quick glance, you're creating an Entity named "Cube" and trying to destroy one named "Ogre".
0 x

Carlyone
Kobold
Posts: 38
Joined: Thu Jul 05, 2012 3:51 pm

Re: Memory Issues on iOS

Post by Carlyone » Thu Mar 14, 2013 3:51 pm

Yeah... cheers for pointing that out. I've sorted that little one but sadly still ending up with 1.91MB usage.
0 x

User avatar
masterfalcon
OGRE Team Member
OGRE Team Member
Posts: 4270
Joined: Sun Feb 25, 2007 4:56 am
Location: Bloomington, MN
Contact:

Re: Memory Issues on iOS

Post by masterfalcon » Thu Mar 14, 2013 4:50 pm

What are you currently using to track the memory usage? Have you tried simply clearing out the entire resource group rather than doing it one at a time?
0 x

Carlyone
Kobold
Posts: 38
Joined: Thu Jul 05, 2012 3:51 pm

Re: Memory Issues on iOS

Post by Carlyone » Thu Mar 14, 2013 5:24 pm

I'm just using the Profiler tool that comes with Xcode.

I added in a few calls, from what I could find from about the web, for destroying resource groups. I went very OTT but that's ok for now. Sadly after all my attempts it still at 1.91MB.

Here's the revised removal code:

Code: Select all

// Clear the mesh
    
        Ogre::MeshManager::getSingleton().unload("ogrehead.mesh");
        Ogre::MeshManager::getSingleton().remove("ogrehead.mesh");
        
        //Cleanup the node
        Ogre::SceneNode* node = OgreFramework::getSingletonPtr()->m_pSceneMgr->getSceneNode("CubeNode");
        
        Ogre::SceneNode::ObjectIterator objIter = node->getAttachedObjectIterator();
        while(objIter.hasMoreElements()){
            Ogre::MovableObject * obj = objIter.getNext();
            node->detachObject(obj);
            
            if(OgreFramework::getSingletonPtr()->m_pSceneMgr->hasManualObject(obj->getName())){
                OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyManualObject(obj->getName());
            }
            OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyMovableObject(obj);
            
            obj = NULL;            
        }
        node->removeAndDestroyAllChildren();
        
        OgreFramework::getSingletonPtr()->m_pSceneMgr->destroyEntity("Cube");
        OgreFramework::getSingletonPtr()->m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(node->getName());
        
        node = NULL;
        
        // Clear the materials
        
        Ogre::MaterialManager::getSingleton().unload("Ogre/Earring");
        Ogre::MaterialManager::getSingleton().remove("Ogre/Earring");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("Ogre/Earring", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("Ogre/Earring");
        
        Ogre::MaterialManager::getSingleton().unload("Ogre/Skin");
        Ogre::MaterialManager::getSingleton().remove("Ogre/Skin");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("Ogre/Skin", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("Ogre/Skin");
        
        Ogre::MaterialManager::getSingleton().unload("Ogre/Tusks");
        Ogre::MaterialManager::getSingleton().remove("Ogre/Tusks");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("Ogre/Tusks", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("Ogre/Tusks");
        
        Ogre::MaterialManager::getSingleton().unload("Ogre/Eyes");
        Ogre::MaterialManager::getSingleton().remove("Ogre/Eyes");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("Ogre/Eyes", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("Ogre/Eyes");
        
        // Clear the textures
        Ogre::TextureManager::getSingleton().unload("GreenSkin.jpg");
        Ogre::TextureManager::getSingleton().remove("GreenSkin.jpg");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("GreenSkin.jpg", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("GreenSkin.jpg");
        
        Ogre::TextureManager::getSingleton().unload("spheremap.png");
        Ogre::TextureManager::getSingleton().remove("spheremap.png");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("spheremap.png", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("spheremap.png");
        
        Ogre::TextureManager::getSingleton().unload("tusk.jpg");
        Ogre::TextureManager::getSingleton().remove("tusk.jpg");
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("tusk.jpg", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("tusk.jpg");
        
        Ogre::ResourceGroupManager::getSingleton().undeclareResource("Ogre.material", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("Ogre.material");

        Ogre::ResourceGroupManager::getSingleton().undeclareResource("ogrehead.mesh", "Ogre");
        Ogre::ResourceGroupManager::getSingleton().deleteResource("ogrehead.mesh");
        
        // Remove any unused resources
        Ogre::MeshManager::getSingleton().removeUnreferencedResources();
        Ogre::TextureManager::getSingleton().removeUnreferencedResources();
        Ogre::MaterialManager::getSingleton().removeUnreferencedResources();
        
        Ogre::ResourceGroupManager::getSingleton().unloadUnreferencedResourcesInGroup("Ogre");
        
        Ogre::ResourceGroupManager::getSingleton().unloadResourceGroup("Ogre");
        Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("Ogre");
        Ogre::ResourceGroupManager::getSingleton().removeResourceLocation("Ogre");
If i'm missing any calls please let me know.
0 x

User avatar
masterfalcon
OGRE Team Member
OGRE Team Member
Posts: 4270
Joined: Sun Feb 25, 2007 4:56 am
Location: Bloomington, MN
Contact:

Re: Memory Issues on iOS

Post by masterfalcon » Thu Mar 14, 2013 5:34 pm

My best guess is that you're seeing memory allocated by iOS for the texture data that it's keeping cached before releasing it later. Perhaps try using the allocations instrument to track alloc/deallocs and see if you can see what isn't being released.
0 x

Carlyone
Kobold
Posts: 38
Joined: Thu Jul 05, 2012 3:51 pm

Re: Memory Issues on iOS

Post by Carlyone » Thu Mar 14, 2013 7:01 pm

I was really hoping not to have to sift through allocations, I take it those calls would cause it to clean up correctly on Windows/Mac etc.

I'll give it a go, see if I can separate out the allocations for just the textures.

Will let you know how it goes.

Cheers for the help so far.
0 x

Carlyone
Kobold
Posts: 38
Joined: Thu Jul 05, 2012 3:51 pm

Re: Memory Issues on iOS

Post by Carlyone » Tue Mar 19, 2013 3:51 pm

After much looking it seemed that it was the images not being released, so ensure I got removed everything I now use the loop below. It does require that all new resources you create go into their own groups but for our purposes it's ideal.

Code: Select all

// Just a group name for this example
std::string groupName = "Ogre";
Ogre::ResourceGroupManager::ResourceManagerIterator iter = Ogre::ResourceGroupManager::getSingleton().getResourceManagerIterator();
while(iter.hasMoreElements()){
    Ogre::ResourceManager* manager = iter.getNext();
    Ogre::ResourceManager::ResourceMapIterator resourceMapIter = manager->getResourceIterator();
    while (resourceMapIter.hasMoreElements()){
        Ogre::ResourcePtr resource = resourceMapIter.getNext();
        if(resource->getGroup().compare(groupName) == 0){
            std::cout << resource->getName() << " | " << resource->getGroup() << std::endl;
            manager->unload(resource->getName());
        }
    }
}
Ideally I would remove all the resources but that causes issues with reloading the Entity (the entity loads but is invisible). But for now the unload knocks off pretty much all of the memory.

It also seems to work better if the mesh, entity and node are removed before removing the textures.

Hope someone else finds this of use.
0 x

Post Reply