[C++-sig] alternative smart pointer (intrusive_ptr) example

Jeff Webb jeff.webb at nta-inc.net
Mon Jul 28 17:53:34 CEST 2008


David Abrahams wrote:
> on Thu Jul 24 2008, Jeff Webb <jeff.webb-AT-nta-inc.net> wrote:
> 
>> The boost::python library provides excellent support for wrapping C++
>> objects managed by boost::shared_ptr reference counting smart
>> pointers.  I am attempting to achieve similar functionality with a
>> little less memory overhead by embedding the reference count in the
>> managed object and using boost::intrusive_ptr instead.
> 
> Why?  Have you profiled the memory use of shared_ptr and found it to be
> a problem?

I investigated the memory usage of shared_ptr by running valgrind on a test program and by looking at the shared_ptr source code.  My findings are summarized in this post:

http://mail.python.org/pipermail/c++-sig/2008-July/013786.html

I am designing a C++ library from the ground up, so I am not tied to any existing conventions (base classes, memory management schemes, etc.).  I want to be able to expose the fundamental building blocks of my library to python, but I want to allow the library to be used without python as well.  I have decided to use smart pointers internally in my C++ library to lay the foundation for seamless integration with python.  Some of my library building blocks are very small, and users will most likely have a large number of instances, so the overhead of the internal memory management scheme is a concern.  I am less concerned by the overhead of the python wrappers, since I expect a small percentage of these objects to by wrapped by python at any given time.

It think that by using intrusive_ptr, I can save one raw pointer's worth of memory for every smart pointer I use, and another raw pointer's worth of memory (plus maybe an int) for the managed objects themselves.

I have included the highlights of my previous email below, but you can use the link above if you want to look at the full post.  I would be interested in hearing any thoughts you may have on any of this.

Thanks,

Jeff

-------- Original Message --------
Date: Thu, 17 Jul 2008 18:02:26 -0500
From: Jeff Webb <jeff.webb at nta-inc.net>
To: Development of Python/C++ integration <c++-sig at python.org>
Subject: shared_ptr vs. intrusive_ptr

[...]

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)
   vtable pointer?   (4 or 8 bytes)
 X *                 (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

[...]



More information about the Cplusplus-sig mailing list