Re: [osg-users] osg::DeleteHander - the good, the bad and ugly
I tried a little brut test about smart pointer from osg and the similar approch in boost with instrusive_ptr here the result with the source code: PROFILE_ROOT prt 100.00 glb 100.00 - time 31.785504 avg 31.785504 ncall 1 osg_smprt 2.85 glb 2.85 - time 0.905553 avg 0.905553 ncall 1 boost_sm prt 2.84 glb 2.84 - time 0.901856 avg 0.901856 ncall 1 boost2 prt 23.95 glb 23.95 - time 7.611869 avg 7.611869 ncall 1 osg2 prt 70.37 glb 70.37 - time 22.366193 avg 22.366193 ncall 1 Cedric Robert Osfield wrote: Hi André, On 8/31/07, André Garneau [EMAIL PROTECTED] wrote: FYI you might want to check the Boost::intrusive_ptr implementation (similar in concept to OSG's ref_ptr) as it is using an underlying implementation that does atomic reference counting (using CPU native Interlocked test/increments). Note that I'm not suggesting to use Boost, just to get ideas from this implementation. Thanks for the suggestion. I'm chasing bugs right now. Could members of the community have a look into this? i.e. the possibility of adding atmoic counts into OpenThreads and ref_ptr. Cheers, Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org /* # # Copyright (C) 2007 Cedric Pinson # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Authors: # Cedric Pinson [EMAIL PROTECTED] # # */ #ifdef HAVE_CONFIG_H #include ../config.h #endif #include iostream #ifdef USE_NPROFILE #include nprofile/profile.h #endif #include cstdlib #include osg/Referenced #include osg/ref_ptr #include cmath #include boost/config.hpp #include boost/shared_ptr.hpp #include boost/intrusive_ptr.hpp struct Test : public osg::Referenced { protected: public: int value; Test(): value(1) {} void test1() { value+=1;} void test2() { value+=2;} }; struct TestBoost { unsigned int count; TestBoost(): count(0) { value = 1; } int value; void test1() { value+= 1;} void test2() { value+=2;} }; void intrusive_ptr_add_ref(TestBoost * p) { ++p-count; } void intrusive_ptr_release(TestBoost * p) { if(--p-count == 0) delete p; } static boost::intrusive_ptrTestBoost test_boost= new TestBoost; static osg::ref_ptrTest test_osg = new Test; void testboost(int n) { NPROFILE_SAMPLE(boost_sm); for (int i = 0;i n; i++) { for (int j = 0;j n; j++) { test_boost-test1(); test_boost-test2(); test_boost-test1(); test_boost-test2(); test_boost-test1(); test_boost-test2(); } } } void testboost2(int n) { NPROFILE_SAMPLE(boost2); for (int i = 0;i n; i++) { boost::intrusive_ptrTestBoost test_boost2; boost::intrusive_ptrTestBoost test_boost3; test_boost2 = test_boost; test_boost3 = test_boost2; test_boost = test_boost3; } } void testosg(int n) { NPROFILE_SAMPLE(osg_sm); for (int i = 0;i n; i++) { for (int j = 0;j n; j++) { test_osg-test1(); test_osg-test2(); test_osg-test1(); test_osg-test2(); test_osg-test1(); test_osg-test2(); } } } void testosg2(int n) { NPROFILE_SAMPLE(osg2); for (int i = 0;i n; i++) { osg::ref_ptrTest test_osg2; osg::ref_ptrTest test_osg3; test_osg2 = test_osg; test_osg3 = test_osg2; test_osg = test_osg3; } } void func(int arg) { // NPROFILE_SAMPLE(root); testosg(arg); testboost(arg); testboost2(arg); testosg2(arg); } int main(int argc , char **argv) { unsigned int arg = 2147483647; std::cout arg std::endl; nprf::GetProfiler()-Reset(); func(arg); nprf::GetProfiler()-EndProfile(); nprf::GetProfiler()-GetRootNode()-DisplayFlatStats(std::cout); std::cout test_osg-value std::endl; std::cout test_boost-value std::endl; return 0; } ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
[osg-users] osg::DeleteHander - the good, the bad and ugly
Hi All, With the introduction of the new DrawThreadPerContext and CullThreadPerCameraDrawThreadPerContext threading models came the use the osg::DeleteHandler, its not used in the other threading models as it isn't required. The DeleteHandler roles is to cache objects that were being deleted for a couple of frames to allow the rendering backend to dispatch all the data from StateSet and Drawables into the OpenGL FIFO without these objects being deleted from under them. Normally the scene graph uses ref_ptr everywhere to stop objects from being deleted whilst still being used, and this is really successfully and very reliable, has been for many years. But.. its only reliable if you use it, and the rendering back end of the OSG has used C pointers rather than ref_ptr so it hasn't had this safety net. The reason for not using ref_ptr is purely performance considerations - when you might be display 10's of thousands of Drawables per frame and near 100 frames per second you could easily be doing a million ref/unref per second so it is expensive - how expnsive? I tested this afternoon and saw a 6% frame rate hit on CPU limited scenes with adding using of ref_ptr into the rendering backend. Now DeleteHandler provides the safety net required to allow use to keep using C pointers in the rendering backend, and avoids the 6% performance penalty, which means the DrawThreadPerContext and CullThreadPerCameraDrawThredPerContext maximize the gain over only SingleThreaded and CullDrawThreadPerContext. So that's the good, slightly better performance. The bad is obviously the extra complexity involved in Referenced and osgViewer required to manage the DeleteHandler. Since this is all written and working and largely hidden from general users this its not such a bad thing. But the ugly... clean up of the application does get more awkward as the DeleteHandler defers deletion until a DeleteHandler::flush() is called, and also this caching mechansim needs to be turned off. Now I've added code into osgViewer to automatically do this for you, and this works to an extent... but its turned out that it's not a robust solution, with users coming across problems with crashes on exit - I believe due to how the DeleteHandler change the order of destruction. Potentially I could write a cleanUpOSG() function that you call on exit, or perhaps even come up with some clever C++ way of destructing things, but its all more complexity to push back on to users, and something almost certainly that is going to cause problems with it not used correctly or not all, or called when it shouldn't be etc. I've come to a point now that I've decided with DeleteHandler I was possible being too clever, and in the greater schemes of things its complicated not just in coding, but in scene graph debugging and usage. Pushing it further is really just put a plaster a broken concept. So in svn I have checked in the use of ref_ptrStateSet in include/osgUtil/StateGraph, and ref_ptrDrawable in include/osgUtil/RenderLeaf. I have also disable the use of DeleteHandler. The new code and old code still sit alonside each other and #define toggles between the two. The default is to use ref_ptr and not to use DeleteHandler. What might the effect be on you? For most it'll probably be a negligible hit in performance as you probably aren't CPU (in cull) limited, for those that are then you might see a ~6% fps hit. The upside and the motivation for this change is that crash on exit problems related to DeleteHandler should now be gone. This change isn't the end of road for this issue - I'd like to find a way to avoid or at least minimize the performance penalty associated with the use of ref_ptr in the rendering backend. Is it time to revisit atomic reference counting? Is there another scheme we can introduce in place of ref_ptr for the rendering backend? From the community I would like feedback, especially those who've seen crash on exit - do a svn update and let me know if the crashes are gone. Also those with expertise on atmoic ref counting please step forward :-) Cheers, Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] osg::DeleteHander - the good, the bad and ugly
Hi André, On 8/31/07, André Garneau [EMAIL PROTECTED] wrote: FYI you might want to check the Boost::intrusive_ptr implementation (similar in concept to OSG's ref_ptr) as it is using an underlying implementation that does atomic reference counting (using CPU native Interlocked test/increments). Note that I'm not suggesting to use Boost, just to get ideas from this implementation. Thanks for the suggestion. I'm chasing bugs right now. Could members of the community have a look into this? i.e. the possibility of adding atmoic counts into OpenThreads and ref_ptr. Cheers, Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org