postgame

boost의 메모리풀은 4가지 종류를 가지고 있습니다.

1. pool - 단순한 메모리 풀
단순히 malloc하고 free만 하는 기능을 가지고 있습니다.
주석대로 지역으로 선언하면 지역적으로 쓰입니다. 할당 실패시에는 Null(0)을 반환합니다.

  1. void func()
  2. {
  3.   boost::pool<> p(sizeof(int));
  4.   for (int i = 0; i < 10000; ++i)
  5.   {
  6.     int * const t = p.malloc();
  7.     ... // t로 작업을 합니다; free하지 않아도 좋습니다.
  8.   }
  9. } // 함수가 종료되면, p는 파괴되고 할당된 int들은 암시적으로 free됩니다.

2. singleton_pool - 싱글톤 메모리풀
싱글톤을 지원하는 메모리 풀입니다.
명시적으로 할당해제하지 않는 한 종료 때까지 메모리가 남아있습니다.

  1. struct MyPoolTag { };
  2.  
  3. typedef boost::singleton_pool<MyPoolTag, sizeof(int)> my_pool;
  4. void func()
  5. {
  6.   for (int i = 0; i < 10000; ++i)
  7.   {
  8.     int * const t = my_pool::malloc();
  9.     ... // t로 작업을 합니다; free하지 않아도 좋습니다.
  10.   }
  11.   // 명시적으로 모든 할당된 int를 해제시킵니다.
  12.   my_pool::purge_memory();
  13. }
  14.  

특이하게도 thread-safety합니다만, 하지만, 단순 pool 처럼 malloc, free만 지원해서
딱히 쓸일은 없을 것 같네요. 마찬가지 실패하면 Null을 반환합니다.


3. pool_alloc
예외를 사용하는 메모리풀입니다. 싱글톤 메모리풀 인터페이스로 만들었고, 표준 Allocator 클래스를 지원하군요.
그럼 stl에 넣어서 사용할 수 있다는 뜻인데.. 이부분은 저도 해보질 못해서 뭐라 못하겠군요.
아무튼 그렇탑니다.

4. object_pool
우리가 원하는(?) 메모리풀이 되겠습니다.
일반적인 메모리풀처럼 템플릿으로 받은 인자를 청크로 나눠 할당해주고, 생성자와 파괴자도
호출해줍니다.
실패하면 마찬가지 Null을 리턴합니다.

  1. #include <iostream>
  2. #include <boost/pool/object_pool.hpp>
  3. using namespace std;
  4.  
  5. class AAA
  6. {
  7. public:
  8.     AAA() { cout<<"construct"<<endl;}
  9.     ~AAA() { cout<<"destory"<<endl;}
  10.     void print() { cout<<"hello"<<endl;}
  11. };
  12.  
  13. void func()
  14. {
  15.     boost::object_pool<AAA> p(10); //할당 갯수를 넣습니다.디폴트는 32
  16.    
  17.     for(int i=0; i<10; ++i)
  18.     {
  19.         AAA *a = p.construct();
  20.         a->print();
  21.         p.destroy(a);
  22.     }
  23. }
  24.  
  25. int main()
  26. {
  27.     func();
  28.     getchar();
  29. }

다른 부스트의 메모리풀처럼 malloc, free를 사용할 수도 있습니만,
그러면 생성자와 파괴자를 호출할 수 없습니다.
new와 delete처럼 construct와 destory를 사용해야만 합니다.
물론 4개를 섞어 쓰면 꼬이겠죠?

메모리풀을 지역적으로 사용하면 내가 다 해제하지 않아도, 할당해준 것은
소멸자를 모두 부르고 해제해줍니다. 이건 편하네요

주의할 점은 object_pool은
처음 생성될때 메모리를 만들지 않고.. 처음 메모리를 할당 할때 메모리를 만듭니다.

  1. boost::object_pool<AAA> p(10); //그니깐 요때 동적메모리 할당하지 않고..
  2. AAA *a = p.construct();        //이때 한다는거죠.

사용할때 동적 메모리를 할당하는건 stl철학과도 맞습니다만,
우리 같은 서버 개발자들은 보통 동적 메모리 할당을 미리 해놓길 원하니,
최초에 아무거라도 할당 받아서 동적할당을 해놓는게 좋겠군요.

할당된 메모리가 넘어가게 요청이 들어오면 메모리 크기를 2배로 늘립니다.
가령 10개를 생성하게 해놓고 10개 할당되면 20개로 메모리 크기를 늘린다는거죵.

부스트 메모리풀의 공통적으로 지원하는 함수들은 아래와 같습니다.

bool is_from(element_type * const chunk) const
 - 해당 청크가 메모리풀에 속해있는지 체크해 줍니다.
size_type get_next_size() const
- 다음 할당시킬 동적 메모리 크기가 얼마나 될것인지를 되돌려 줍니다.
  고로 처음 생성자에 10개로 동적 할당하고 첫 construct하면 20을 리턴합니다.
 10개를 모두 construct하면 40을 리턴합니다.

자세한건..
http://www.boost.org/doc/libs/1_39_0/libs/pool/doc/index.html  - 부스트 공식 사이트
http://jacking75.cafe24.com/Boost/Pool/index.htm - 흥배님 사이트(일본 사이트를 번역하셨네요)
에서 얻을 수 있습니다만..
boost.org자체가 그리 친절한 사이트가 아니니.. 실습하면서 익히는 수밖에 없을것 같네요.

메모리풀 구현이 그리 어려운건 아닙니다만,
이미 검증된 메모리풀을 가져다 쓰면
성능과 다른 팀원과의 협업시에 휠 유리할것이라 생각됩니다.

Posted by 중원_