2011年2月27日日曜日

shared_ptrとintrusive_ptrの実装方法とかパフォーマンスとか

最近、C++のメモリの動的確保や管理の方法についていろいろ調べまわっていたので、わかったことをメモしておく。

まずは、スマートポインタについて。

スマートポインタとは、登録したオブジェクトがどこからも参照されなくなったさい、自動でdeleteを呼んでくれる便利クラス。ガベージコレクションの実装された言語ばかりさわってた自分にとって、これはすごくありがたい。

shared_ptrやauto_ptr、intrusive_ptr等が存在するけど、今回はshared_ptrとintrusive_ptrの使い方とパフォーマンスを比較してみた。



#include <iostream>
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>

#include <time.h>
#include <sys/time.h>

class testClass {
 
public:
 testClass():refCount(0) {}
 ~testClass()   {}
 
 static inline boost::intrusive_ptr<testClass>  createInPtr()
 {
  return boost::intrusive_ptr<testClass>(new testClass());
 }
 
 static inline boost::shared_ptr<testClass>     createShPtr()
 {
  return boost::shared_ptr<testClass>(new testClass());
 }
 
private:
 
 // intrusive_ptr用 参照カウンタ
 int refCount;
 
 // intrusive_ptr用 参照が増えた時呼ばれる処理
 friend void intrusive_ptr_add_ref( testClass* p )
 {
  p->refCount++; 
 }
    
 // intrusive_ptr用 参照が減った時呼ばれる処理 参照が0になるとdeleteが呼ばれる。
 friend void intrusive_ptr_release( testClass* p )
 { 
  p->refCount--;
  if (p->refCount <= 0) delete p;
 }
 
};

typedef boost::intrusive_ptr<testClass> inPtr;
typedef boost::shared_ptr<testClass> shPtr; 

// 時間計測用
double gettimeofday_sec()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + (double)tv.tv_usec*1e-6;
}

int main () {
 int max_count = 1000000;
 double start, end;
 
 // 比較用 ふつーに new delete ////////////// 
 start = gettimeofday_sec();
 for (int i = 0; i < max_count; i++){
  testClass *tp = new testClass();
  delete tp;
 }
 end   = gettimeofday_sec();
 printf("%f new delete\n", end - start);
 
 // shared_ptr /////////////////////////// 
 start = gettimeofday_sec();
 for (int i = 0; i < max_count; i++){
  shPtr tcShp = testClass::createShPtr();
 }
 end   = gettimeofday_sec();
 printf("%f shared_ptr\n", end - start);
 
 // intrusive_ptr ///////////////////////
 start = gettimeofday_sec();
 for (int i = 0; i < max_count; i++){
  inPtr tcInp = testClass::createInPtr();
 }
 end   = gettimeofday_sec();
 printf("%f intrusive_ptr\n", end - start);
 
    return 0;
}

実行速度はこんな感じになった
0.065289 new delete
0.178643 shared_ptr
0.059417 intrusive_ptr
shared_ptrがかなり遅い。内部で参照カウンタをnewしてるせいか。
てか、new delete自体も意外なほどマイペース。

メモリプールをつかってパフォーマンスの改善を試してみたので次回にまとめる。

0 件のコメント:

コメントを投稿