Hi David, First up I'd refer back to my previous email. Using ten of thousands of nodes and shape drawables is really really bad for performance with much better alternatives such as using point sprites or geometry instancing. These solutions also have much much much lower memory usage. So... once you fix your scene to make it efficient you'll get great performance and low memory usage.
Second I'd mention that scene graph manages it's own scene graph objects such as nodes, statesets, state attributes, geometry, arrays etc, then there are the OpenGL ID's the scene graph maintains there refer to OpenGL objects such as display lists, texture objects, VBO's, the actual objects reside in OpenGL driver memory. The OpenGL objects can only be deleted from a graphics thread so even if you delete the scene graph objects the OpenGL memory associate with them isn't freed immediately, instead it's cached by the OSG in buffers that are clear when the graphics threads run. These buffers for OpenGL object are also kept around for reuse so that the OSG is able to make use of already created OpenGL objects like textures, as creating and delete OpenGL is relatively expensive this ability is significant gain for performance. Finally, rewrite your app to use efficient scene graph and OpenGL representation for your sphere and stop worry so much about memory the OSG knows what it's doing, as long as you are sensible with the scene graph you throw at it will be do the right thing. Robert. On Wed, Oct 26, 2011 at 8:24 PM, David Benoit <[email protected]> wrote: > Hi, > > I know memory issues are a FAQ for OSG. I have read the FAQ for this forum, > and searched for answers elsewhere. I don't think this issue has been > covered. (I'm happy to be pointed to a reference I missed.) > > This is also related to my other recent posts: > http://forum.openscenegraph.org/viewtopic.php?p=43569#43569 > http://forum.openscenegraph.org/viewtopic.php?t=8997 > > The issue may not even be an OSG issue, but so far it appears to be. Any > suggestions would be appreciated. If I'm doing something wrong or > non-standard, I haven't found it in this forum or any other resources I've > found on the net. > > I have a program in which I want to add and remove many things (spheres and > geometries with many texture-mapped polygons). When I add a lot of things, > memory usage goes up. When I remove them, all the referenceCounts for the > objects I added return to 0 as they should. > > Memory usage doesn't go down to 0, though. It declines slightly. It's not a > memory leak, though, because when I add a bunch of objects again, memory > usage just goes back up to what it was before. However, when I remove the > objects, I'd really like to get the memory back. > > This isn't an OS issue. My OS (ubuntu) reflects freed memory immediately in > the system monitor. > > Interestingly, if I create my spheres by using a shared geode for each > instance, I *do* get the memory back after removing the objects from the > scene. > > So, who has that memory? > > The code below demonstrates this. Run it like this: > > $ ./testViewer 30000 noshare 1 5 true > $ ./testViewer 200000 share 1 5 true > > Example results are in the attached graphs. > > Thank you! > > > > Code: > > // Remove the spaces in the #includes. BBCode didn't show the > // include names when there were no spaces. > #include < iostream > > #include < iomanip > > #include < sys/time.h > > #include < string.h > > #include < stdlib.h > > > #include < osgViewer/Viewer > > #include < osgViewer/CompositeViewer > > #include < osgGA/TrackballManipulator > > #include < osg/PositionAttitudeTransform > > #include < osg/ShapeDrawable > > > #define UNIFORM(a,b) ((((double)rand() / (double)RAND_MAX) * ((b)-(a))) + (a)) > > double getCurrentTime() { > struct timeval time; > gettimeofday(&time, 0); > return time.tv_sec + (time.tv_usec * 0.000001); > } > > int main(int argc, char* argv[]) > { > > srand((unsigned int) getCurrentTime()); > > size_t numSpheres = 1; > bool shareGeode = false; > size_t maxIterations = 1; > double waitTime = 1.0; > bool pause = true; > > // Command line args. > if ((argc < 2) || (argc > 6)) return 1; > if (argc >= 2) numSpheres = atoi(argv[1]); > if (argc >= 3) shareGeode = (strcmp("share", argv[2]) == 0); > if (argc >= 4) maxIterations = atoi(argv[3]); > if (argc >= 5) waitTime = (double)atoi(argv[4]); > if (argc >= 6) pause = (strcmp("true", argv[5]) == 0); > > // The scene goes here. > osg::ref_ptr<osg::Group> sceneRoot = new osg::Group(); > > // We keep our own references to all the objects so that we > // can check their reference counts later. > std::vector<osg::ref_ptr<osg::PositionAttitudeTransform> > pats; > std::vector<osg::ref_ptr<osg::Geode> > geodes; > std::vector<osg::ref_ptr<osg::ShapeDrawable> > shapes; > > // If shareGeode is true, construct the scene by sharing a single sphere > // geode among all PATs for each sphere that is drawn. > if (shareGeode) { > osg::ref_ptr<osg::Geode> sphereGeode = new osg::Geode(); > osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(osg::Vec3(0,0,0),0.2); > osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = > new osg::ShapeDrawable(sphere); > > sphereGeode->addDrawable(sphereDrawable); > > shapes.push_back(sphereDrawable); > geodes.push_back(sphereGeode); > } > > osgViewer::Viewer viewer; > viewer.setUpViewInWindow( 0, 0, 1200, 900 ); > viewer.setSceneData(sceneRoot); > viewer.setCameraManipulator(new osgGA::TrackballManipulator()); > viewer.realize(); > > // This whole state-machine cruft is just to give the system monitor > // time to reflect changes in the memory usage so we can see them. > typedef enum { ADD, REMOVE, QUIT } Action; > Action action = ADD; > double lastActionTime = 0.0; > bool quit = false; > size_t numIterations = 0; > size_t geodeIndex; > while (!quit && !viewer.done()) { > > if ((getCurrentTime() - lastActionTime) > waitTime) { > lastActionTime = getCurrentTime(); > switch (action) { > case ADD: > { > for (size_t ii=0; ii<numSpheres; ++ii) { > // Create a new geode or reuse the one already created. > if (shareGeode) { > geodeIndex = 0; > } else { > osg::ref_ptr<osg::Geode> sphereGeode = new osg::Geode(); > osg::ref_ptr<osg::Sphere> sphere = > new osg::Sphere(osg::Vec3(0,0,0),0.2); > osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = > new osg::ShapeDrawable(sphere); > > sphereGeode->addDrawable(sphereDrawable); > > geodeIndex = geodes.size(); > shapes.push_back(sphereDrawable); > geodes.push_back(sphereGeode); > } > > // Move the sphere to a random location. > double x = UNIFORM(-1,1); > double y = UNIFORM(-1,1); > double z = UNIFORM(-1,1); > osg::ref_ptr<osg::PositionAttitudeTransform> sphereXform = > new osg::PositionAttitudeTransform(); > osg::Vec3 position(x,y,z); > sphereXform->setPosition(position); > pats.push_back(sphereXform); > > // Add it to the scene. > sphereXform->addChild(geodes[geodeIndex]); > sceneRoot->addChild(sphereXform); > } > > std::cout << "Execution times for viewer.frame(): "; > for (size_t ff=0; ff<5; ff++) { > double start, stop; > start = getCurrentTime(); > viewer.frame(); > stop = getCurrentTime(); > std::cout << (stop - start) << ", "; std::cout.flush(); > } > std::cout << std::endl; > > > action = REMOVE; > } > break; > case REMOVE: > { > sceneRoot->removeChildren(0,sceneRoot->getNumChildren()); > > // Do this to give viewer a chance to release everything. > if (pause) for (size_t ff=0; ff<10; ff++) { viewer.frame(); } > > // The refCount for the PATs should all be 1 now. They no longer > // exist as children of sceneRoot, but they are referenced in the > // vector 'pats'. > bool patsOK = true; > for (size_t pp=0; pp<pats.size(); ++pp) { > if (pats[pp]->referenceCount() != 1) patsOK = false; > } > if (!patsOK) std::cout << "PAT refCounts wrong." << std::endl; > > // Release all the pats. > pats = std::vector<osg::ref_ptr<osg::PositionAttitudeTransform> >(); > // Do this to give viewer a chance to release everything. > if (pause) for (size_t ff=0; ff<10; ff++) { viewer.frame(); } > > // The refCount for the geodes should be 1 because they no longer > // exist as a child of any PAT, but they are referenced in the > // geodes vector. > bool geodesOK = true; > for (size_t gg=0; gg<geodes.size(); ++gg) { > if (geodes[gg]->referenceCount() != 1) geodesOK = false; > } > if (!geodesOK) std::cout << "Geode refCounts wrong." << std::endl; > > // The refCount for the shapeDrawables should be 2 because they > // are each a child of a geode and also referenced in the > // shapes vector. > bool shapesOK = true; > for (size_t ss=0; ss<shapes.size(); ++ss) { > if (shapes[ss]->referenceCount() != 2) shapesOK = false; > } > if (!shapesOK) std::cout << "Shape refCounts wrong." << std::endl; > > if (!shareGeode) { > // If we're not sharing the geode, we clear these vectors > // because we'll refill them on the next iteration. > geodes = std::vector<osg::ref_ptr<osg::Geode> >(); > shapes = std::vector<osg::ref_ptr<osg::ShapeDrawable> >(); > > // Do this to give viewer a chance to release everything. > if (pause) for (size_t ff=0; ff<10; ff++) { viewer.frame(); } > } > > > action = ADD; > numIterations++; > if (numIterations >= maxIterations) { > action = QUIT; > } > } > break; > > case QUIT: quit = true; break; > > } > } > > viewer.frame(); > } > return 0; > } > > > > > ------------------ > Read this topic online here: > http://forum.openscenegraph.org/viewtopic.php?p=43571#43571 > > > > > _______________________________________________ > osg-users mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > > _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

