[C++-sig] shared_ptr vs. intrusive_ptr

Jeff Webb jeff.webb at nta-inc.net
Mon Jul 21 16:50:45 CEST 2008


Any comments?  Surely someone has looked at the memory usage of shared_ptr.  I'm not asking someone to verify the overhead down to the byte, but I would like to have confirmation that the numbers I posted are what one would generally expect, and that there is some motivation to pursue an alternative implementation in certain cases.  If I am totally off-base here, or if no one else is interested in this issue, then I don't see any point in posting my proposed solution for review.

Jeff Webb wrote:
> Since we're discussing the topic of shared_ptr, intrusive_ptr, and other 
> custom smart pointers, I have a few observations and some related 
> questions that I would like to share.  I would love to hear some 
> comments from the experts on these.
> 
> (1) It seems that if you are designing a C++ library from the ground up 
> to use with boost::python, it makes a lot of sense to use smart pointers 
> internally in your C++ library.  Python uses reference counting to 
> manage objects, so if you use reference counting in your C++ library, 
> you are laying the foundation for a seamless python interface instead of 
> fighting Python's memory management.
> 
> (2) The boost::python support for shared_ptr is fantastic, and if you 
> make good use of shared_ptrs, many things will 'just work'.
> 
> (3) If you decide to use smart pointers, there are two main reasons 
> *not* to use shared_ptr:    (a) your library uses a custom smart pointer 
> internally
>    (b) the memory usage of shared_ptr is not acceptable
> 
> I have attempted to quantify the memory usage of shared_ptr vs. a simple 
> intrusive_ptr implementation using the attached test program.  I used 
> valgrind to verify the dynamic memory usage.  Here are the results:
> 
> shared_ptr
> ----------
> 
> Each shared_ptr is the size of two raw pointers (one for the managed 
> object, and one for the shared reference count):
> 
>  A total of  8 bytes on x86          or 16 bytes on x86_64
> 
> For each object that is managed by shared_ptrs, a shared reference count 
> must be allocated.  The memory usage for the shared reference count 
> appears to be two integers and two pointers:
> 
>  A total of 16 bytes on x86
>          or 24 bytes on x86_64
> 
> When looking at the shared_ptr source code, I could only find one 
> pointer in the shared reference count, but I cannot reconcile this with 
> the memory usage reported by valgrind.  I suppose it doesn't really 
> matter, but the breakdown I found in the code is listed below.  Maybe I 
> am not looking at the right implementation for my system.
> 
> sp_counted_impl_p:
>  sp_counted_base:
>    int use_count_;   (4 bytes)
>    int weak_count_;  (4 bytes)
>  X *                 (4 or 8 bytes)
>  ???                 (4 or 8 bytes)
> 
> intrusive_ptr
> -------------
> 
> Each intrusive_ptr is the size of a raw pointer:
> 
>  A total of 4 bytes on x86          or 8 bytes on x86_64
> 
> For each object that is being managed by this intrusive_ptr 
> implementation, an extra integer must be added to the object to hold the 
> reference count:
> 
>  A total of 4 bytes on x86 or x86_64
> 
> (5) Summary:  If you are wrapping a relatively small number of objects 
> or you are wrapping very large objects, the overhead of shared_ptr is 
> probably acceptable.  If you are wrapping a large number of very small 
> objects, then a custom intrusive_ptr solution is worth looking into.
> 
> Any comments on these ideas?  Is my summary of shared_ptr memory usage 
> on target?
> 
> Thanks,
> 
> Jeff



More information about the Cplusplus-sig mailing list