Ever since we moved from 1.2 to 2.8.1 of OSG, we've noticed a problem with our
TerraPage databases. We've noticed that memory consumption was getting higher
and higher throughout the lifetime of the application and that texture objects
were being duplicated.
I did some digging to find when this was first introduced. Since I knew this
wasn't an issue with OSG 1.2, I began my search with 2.0 and went forward until
I noticed the memory consumption issue.
The test is quite simple. We load default settings of OSGViewer with one of
our TerraPage databases. With the camera in terrain manipulation mode, we move
the focal to the center of the database and position the camera some distance
from that. We then spin the camera around the database, making sure that
height of the camera does not change. I would then look at the virtual memory
from the OS. In OSG 1.2, our database would sit at an average of 200 MB. This
was also true for 2.0 and 2.2 but NOT for 2.4.
I started digging around and looking at the differences between 2.2 and 2.4.
There were no changes to the TXP plugin, so I started looking at the database
pager and what changed there. There were quite a few changes, but I was able
to narrow it down to revision 8007. This revision is where the
DatabasePager::removeExpiredSubgraphs was rewritten to account for quicker
expiration of subgraphs and better load balancing. In any case, the part of
the code that is important is the following (r8006->r8007):
Code:
if (plod->referenceCount()<=1)
{
// prune PageLOD's that are no longer externally referenced
childrenRemoved.push_back(const_cast<osg::PagedLOD*>(plod));
//osg::notify(osg::NOTICE)<<"_activePagedLODList : pruning no longer
externally referenced"<<std::endl;
remove_plod = true;
}
It seemed odd that removing this section of code would cause the memory issue I
was seeing, so I needed to understand how the TXP plugin works. Here is the
basic scene graph for just a TerraPage database, just to explain what I am
speaking about.
TXPNode
|
---- PagedLOD ---- TXPPagedLOD
|
---- PagedLOD ---- TXPPagedLOD
|
---- PagedLOD ---- Group
|
---- PagedLOD ---- Node
|
---- PagedLOD
Let me try and make some sense of this. When OSGViewer calls readRefNodeFile
for the archive file, a TXPNode, and ONLY the TXPNode, is returned. No
PagedLODs will be registered with the database pager at all. As the scene is
being built up, the TXP plugin begins adding PagedLODs under the TXPNode, and
quite a few of them. When a database request is made, the top level PagedLOD
makes the request. At some undetermined time later, the database pager will
satisfy the request and add to the PagedLOD the information that was returned.
The information returned here is then searched for PageLODs to be registered
into the database pager. At some undetermined time later, the TXP plugin
determines that a subgraph is no longer needed and will sever the link between
the TXPNode and the top level PagedLOD. If the top level PagedLOD did not have
a TXPPagedLOD associated to it, then everything is ok, as the database pager
did not have anything registered to it, but if a TXPPagedLOD w
as registered, the reference count is now a 1, meaning that the database pager
is the only object that owns this. The database pager now calls
removeExpiredChildren on all the registered PagedLODs. Because TXPPagedLODs
sets the number of children that cannot be expired to a 1, this function
basically returns just a quickly as it entered it. Code prior to revision 8007
would have just removed the node from the database's registered paged lods, but
this is not the case at all now.
In any case, I have a simple fix to correct this issue. The TXPPagedLOD can
extend the removeExpiredChildren function call, and if the reference count for
itself is 1, it can include itself in the list of children to remove. Quite a
simple fix for this. It should also be stated that applications using a
TerraPage database should set the _targetMaximumNumberOfPageLOD to 0, since the
database pager would just be holding onto data that is never going to be used
again.
I also have another change I would like to submit with this. Kind of goes
along with the memory issue. I any case, our application allows the user to
change databases. When changing away from a previously loaded TXP database,
the archive file associated to the ReaderWriterTXP is not being released.
Because of this, we are leaking models and texture data for a resource that we
are not going to use again, and if we do come back to it, the TXP plugin just
assumes a new database.
The simplest fix for this issue is to destroy the reference in the
ReaderWriterTXP class when the TXPNode is being destroyed.
I've tested all this for the past couple days now using OSGViewer and our
application. Everything looks good to go and just needs approval. File diffs
provided with the changes. Source changes from revision 11035.
Thanks
Ryan
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=23515#23515
Attachments:
http://forum.openscenegraph.org//files/txp_818.zip
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org