title: Is there a faster C++ Heap allocation/deallocation mechanism available than boost::object_pool?
body: <p>This week I found out about boost::object_pool and was amazed that it was about 20-30% quicker than normal new &amp; delete. </p>
  
  <p>For testing I wrote a small C++ app that uses boost::chrono to time the different heap allocator/deallocator (shared_ptr). The functions itself do a simple loop of 60M iterations with a 'new' and 'delete'. Beneath the code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  #include &lt;memory&gt;
  using std::shared_ptr;
  
  #include &lt;boost/smart_ptr.hpp&gt;
  #include &lt;boost/chrono.hpp&gt;
  #include &lt;boost/chrono/chrono_io.hpp&gt;
  #include &lt;boost/pool/object_pool.hpp&gt;
  
  #include &lt;SSVUtils/SSVUtils.h&gt;
  
  #include "TestClass.h"
  
  const long lTestRecursion = 60000000L;
  
  void WithSmartPtrs()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      for (long i=0; i &lt; lTestRecursion; ++i)
      {
          boost::shared_ptr&lt;TestClass&gt; spTC = boost::make_shared&lt;TestClass&gt;("Test input data!");  
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  void WithSTDSmartPtrs()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      for (long i=0; i &lt; lTestRecursion; ++i)
      {
          std::shared_ptr&lt;TestClass&gt; spTC = std::make_shared&lt;TestClass&gt;("Test input data!");  
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  template&lt;typename T&gt; struct Deleter {
      void operator()(T *p)
      {
          delete p;
      }
  };
  
  
  void WithSmartPtrsUnique()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      for (long i=0; i &lt; lTestRecursion; ++i)
      {
          boost::unique_ptr&lt;TestClass, Deleter&lt;TestClass&gt; &gt; spTC = boost::unique_ptr&lt;TestClass, Deleter&lt;TestClass&gt; &gt;(new TestClass("Test input data!"));  
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  void WithSmartPtrsNoMakeShared()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      for (long i=0; i &lt; lTestRecursion; ++i)
      {
          boost::shared_ptr&lt;TestClass&gt; spTC = boost::shared_ptr&lt;TestClass&gt;( new TestClass("Test input data!"));   
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  
  void WithoutSmartPtrs()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      for (long i=0; i &lt; lTestRecursion; ++i)
      {
          TestClass* pTC = new TestClass("Test input data!"); 
          delete pTC;
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  void WithObjectPool()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      {
          boost::object_pool&lt;TestClass&gt; pool;
          for (long i=0; i &lt; lTestRecursion; ++i)
          {
              TestClass* pTC = pool.construct("Test input data!");    
              pool.destroy(pTC);
          }
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  
  void WithObjectPoolNoDestroy()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      //{
          boost::object_pool&lt;TestClass&gt; pool;
          for (long i=0; i &lt; lTestRecursion; ++i)
          {
              TestClass* pTC = pool.construct("Test input data!");    
              //pool.destroy(pTC);
          }
      //}
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  
  
  void WithSSVUtilsPreAllocDyn()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      {
          ssvu::PreAlloc::PreAllocDyn preAllocatorDyn(1024*1024);
          for (long i=0; i &lt; lTestRecursion; ++i)
          {
              TestClass* pTC = preAllocatorDyn.create&lt;TestClass&gt;("Test input data!"); 
              preAllocatorDyn.destroy(pTC);
          }
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  
  
  void WithSSVUtilsPreAllocStatic()
  {
      boost::chrono::system_clock::time_point startTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "Start time: " &lt;&lt; startTime &lt;&lt; std::endl;
  
      {
          ssvu::PreAlloc::PreAllocStatic&lt;TestClass&gt; preAllocatorStat(10);
          for (long i=0; i &lt; lTestRecursion; ++i)
          {
              TestClass* pTC = preAllocatorStat.create&lt;TestClass&gt;("Test input data!");    
              preAllocatorStat.destroy(pTC);
          }
      }
  
      boost::chrono::system_clock::time_point endTime = boost::chrono::system_clock::now();
      std::cout &lt;&lt; "End time: " &lt;&lt; endTime &lt;&lt; std::endl;
  
      boost::chrono::duration&lt;double&gt; d = endTime - startTime;
      std::cout &lt;&lt; "Duration: " &lt;&lt; d &lt;&lt; std::endl;
  }
  
  
  int main()
  {
      std::cout &lt;&lt; " With OUT smartptrs (new and delete): " &lt;&lt; std::endl;
      WithoutSmartPtrs();
  
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With smartptrs (boost::shared_ptr withOUT make_shared): " &lt;&lt; std::endl;
      WithSmartPtrsNoMakeShared();
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With smartptrs (boost::shared_ptr with make_shared): " &lt;&lt; std::endl;
      WithSmartPtrs();
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With STD smart_ptr (std::shared_ptr with make_shared): " &lt;&lt; std::endl;
      WithSTDSmartPtrs();
  
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With Object Pool (boost::object_pool&lt;&gt;): " &lt;&lt; std::endl;
      WithObjectPool();
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With Object Pool (boost::object_pool&lt;&gt;) but without destroy called!: " &lt;&lt; std::endl;
      WithObjectPoolNoDestroy();
  
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With SSVUtils PreAllocDyn(1024*1024)!: " &lt;&lt; std::endl;
      WithSSVUtilsPreAllocDyn();
  
  
      std::cout &lt;&lt; std::endl &lt;&lt; " With SSVUtils PreAllocStatic(10)!: " &lt;&lt; std::endl;
      WithSSVUtilsPreAllocStatic();
  
  
      return 0;
  }
  </code></pre>
  
  <p>Results:</p>
  
  <pre><code>On Ubuntu LTS 12.04 x64 with GNU C++ 4.6 and boost 1.49                                                                         
  
  
  No smart ptrs (new/delete)                      5,08024     100     5,1387      100     5,1108      100     5,1099  100
  
  
  With boost::shared_ptr No boost::make_shared                        7,36128 2,2810  145     7,34522 2,2065  143     7,28801 2,1772  143     7,3315  143
  
  With boost::shared_ptr and boost::make_shared                       6,60351 1,5233  130     6,82849 1,6898  133     6,61059 1,4998  129     6,6809  131
  
  With std::shared_ptr and std::make_shared                       6,07756 0,9973  120     5,93100 0,7923  115     5,9037  0,7929  116     5,9708  117
  
  
  With boost::unique_ptr                      4,97147 -0,1088 100     5,0428  -0,0959 98      4,96625 -0,1445 97      4,9935  98
  
  
  With boost::object_pool                     3,53291 -1,5473 70      3,60357 -1,5351 70      3,52986 -1,5809 69      3,5554  70
  
  With boost::object_pool (Without calling Destroy)                       4,52430 -0,5559 89      4,51602 -0,6227 88      4,52137 -0,5894 88      4,5206  88
  </code></pre>
  
  <p>Results including SSVUtils PreAllocDyn on my MacBook Pro:
  Compiled with: </p>
  
  <pre><code>  g++-mp-4.8 -I$BOOSTHOME/include -I$SSVUTILSHOME/include  -std=c++11 -O2 -L$BOOSTHOME/lib -lboost_system -lboost_chrono  -o smartptrtest smartptr.cpp
  
   With OUT smartptrs (new and delete): 
  Start time: 1381596718412786000 nanoseconds since Jan 1, 1970
  End time: 1381596731642044000 nanoseconds since Jan 1, 1970
  Duration: 13.2293 seconds
  
   With smartptrs (boost::shared_ptr withOUT make_shared): 
  Start time: 1381596731642108000 nanoseconds since Jan 1, 1970
  End time: 1381596753651561000 nanoseconds since Jan 1, 1970
  Duration: 22.0095 seconds
  
   With smartptrs (boost::shared_ptr with make_shared): 
  Start time: 1381596753651611000 nanoseconds since Jan 1, 1970
  End time: 1381596768909452000 nanoseconds since Jan 1, 1970
  Duration: 15.2578 seconds
  
   With STD smart_ptr (std::shared_ptr with make_shared): 
  Start time: 1381596768909496000 nanoseconds since Jan 1, 1970
  End time: 1381596785500599000 nanoseconds since Jan 1, 1970
  Duration: 16.5911 seconds
  
   With Object Pool (boost::object_pool&lt;&gt;): 
  Start time: 1381596785500638000 nanoseconds since Jan 1, 1970
  End time: 1381596793484515000 nanoseconds since Jan 1, 1970
  Duration: 7.98388 seconds
  
   With Object Pool (boost::object_pool&lt;&gt;) but without destroy called!: 
  Start time: 1381596793484551000 nanoseconds since Jan 1, 1970
  End time: 1381596805774318000 nanoseconds since Jan 1, 1970
  Duration: 12.2898 seconds
  
   With SSVUtils PreAllocDyn(1024*1024)!: 
  Start time: 1381596815742696000 nanoseconds since Jan 1, 1970
  End time: 1381596824173405000 nanoseconds since Jan 1, 1970
  Duration: 8.43071 seconds
  
   With SSVUtils PreAllocStatic(10)!: 
  Start time: 1381596824173448000 nanoseconds since Jan 1, 1970
  End time: 1381596832034965000 nanoseconds since Jan 1, 1970
  Duration: 7.86152 seconds
  </code></pre>
  
  <p>My question:
  Are there, besides shared_ptr/unique_ptr/boost::object_pool more heap/allocation mechanisms that can be used for quick heap allocation/deallocation of large set of objects?</p>
  
  <p>NOTE: I also have more results on other machines and Operating systems.</p>
  
  <p>EDIT 1: Added SSVUtils PreAllocDyn Results
  EDIT 4: Added my compiler commandline options and retested with SSVUtils PreAllocStatic(10)</p>
  
  <p>Thanks</p>