<div dir="ltr">Hi Robert,<br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 21, 2018 at 9:35 AM, Robert Osfield <span dir="ltr"><<a href="mailto:robert.osfield@gmail.com" target="_blank">robert.osfield@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Tim,<br><br><div class="gmail_quote"><span class=""><div dir="ltr">On Thu, 21 Jun 2018 at 08:25, Tim Moore <<a href="mailto:timoore33@gmail.com" target="_blank">timoore33@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Before you move on, the big advantage of std::shared_ptr over intrusive reference counting is that support for weak pointers is rock solid. In the intrusive model, you can't implement thread-safe weak pointers without an auxiliary data structure, which complicates the implementation a lot. I know that one historic OSG performance win for  osg::ref_ptr  was the ability to not do the reference counting if it isn't needed, but with atomic increment / decrement implemented everywhere, do you think there is really much performance advantage for intrusive counting? Also, std::make_shared<>() allocates the shared_ptr control block in the same memory allocation as the shared object, so there need not be a memory fragmentation hit for using shared_ptr.<div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="m_3998380415820970355m_5298850111614736781HOEnZb"><div class="m_3998380415820970355m_5298850111614736781h5"></div></div></blockquote></div></div></div></blockquote><div><br></div></span><div>The big advantage of intrusive reference counting is that the ref_ptr<> holds a pointer to the actual object that you want to access, it's a single jump. shared_ptr<> is literary a pointer to a shared pointer (which is a reference counted object) to a the actual object that you want to access, it's two pointers, two objects vs one pointer and one object.  Scene graphs are predominately memory bandwidth limited so this extra level of indirection is not even close to as efficient as intrusive reference counting.  The only advantage that shared_ptr<> has is that it works with any type, but with a scene graph the types are mostly all under our control there is no cost in complexity of having intrusive reference counting, just stick it into the base class that most classes use anyway and your job is done.<br></div><div><br></div></div></div></blockquote><div>This is not the way shared_ptr is implemented, at least in gcc. The shared pointer contains a pointer to the object as well as to the control block. You could argue that this makes a shared_ptr twice the size of an osg::ref_ptr, but I really can't speculate on the overall effect on memory usage.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div>So... as my aim where possible is to make the VulkanSceneGraph more efficient than the OpenSceneGraph I can't just put chains around my ankles by adopting shared_ptr<>, instead I will acknowledge where the OpenSceneGraph already does something well and following this approach, albeit in a modern C++ way.</div><div><br></div><div>For the thread safe observer_ptr<> you do need a separate auxiliary object, just like the OSG, so in my prototyping this is already what I have done.  I already have an vsg::Auxiliary object that is created when required, this Auxiliary object is for more than just supporting observer_ptr<> though, it also stores optional extra user data.  Doing this shrinks the base vsg::Object/Node classes and improves memory utilization, providing a measurable gain in construction, destruction and traversal of the scene graph over what can be done with the OSG.<br></div></div></div></blockquote><div>What's the measured gain? </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div><br></div><div>When adopting new features of C++ you have to understand what is happening under the hood, for software that is performance critical like a scene graph you have to take the time to make sure</div></div></div></blockquote><div>Agreed :) </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div> there aren't hidden performance costs are, if there is a cost then you have to be really sure that this cost is worth the value it provides.  shared_ptr<>/weak_ptr<> don't cut it for the core scene graph.  There are plenty of other modern C++ features that are really neat and just make life easier without a cost, you'll see this sprinkled everywhere in the VulkanSceneGraph.  <br></div><div><br></div><div><br></div></div></div></blockquote><div>Of course I trust your judgement, but I struggled mightily with weak pointer thread safety back in the day and am happy to be able to make it someone else's problem now. I am very happy that VulkanSceneGraph is coming on the scene!</div><div><br></div><div>Tim </div></div></div></div>