<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    定長內存池之BOOST::pool

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    內存池可有效降低動態申請內存的次數,減少與內核態的交互,提升系統性能,減少內存碎片,增加內存空間使用率,避免內存泄漏的可能性,這么多的優點,沒有理由不在系統中使用該技術。

    內存池分類:

    1、              不定長內存池。典型的實現有apr_pool、obstack。優點是不需要為不同的數據類型創建不同的內存池,缺點是造成分配出的內存不能回收到池中。這是由于這種方案以session為粒度,以業務處理的層次性為設計基礎。

    2、             定長內存池。典型的實現有LOKI、BOOST。特點是為不同類型的數據結構分別創建內存池,需要內存的時候從相應的內存池中申請內存,優點是可以在使用完畢立即把內存歸還池中,可以更為細粒度的控制內存塊。
        與變長的相比,這種類型的內存池更加通用,另一方面對于大量不同的數據類型環境中,會浪費不少內存。但一般系統主要的數據結構都不會很多,并且都是重復申請釋放使用,這種情況下,定長內存池的這點小缺點可以忽略了。

     

    Boost庫的pool提供了一個內存池分配器,用于管理在一個獨立的、大的分配空間里的動態內存分配。Boost庫的pool主要適用于快速分配同樣大小的內存塊,尤其是反復分配和釋放同樣大小的內存塊的情況。使用pool內存池主要有以下兩個優點:

      1. 能夠有效地管理許多小型對象的分配和釋放工作,避免了自己去管理內存而產生的內存碎片和效率低下問題。

      2.  告別程序內存泄漏的煩惱,pool庫會在內部對內存自動進行管理,避免了程序員一不小心而造成的內存泄漏問題。

          pool庫主要提供了四種內存池接口,分別是pool、object_pool、singleton_pool和pool_allocator/fast_pool_allocator。

         

    1)pool

    基本的定長內存池

     

    #include <boost/pool/pool.hpp>

    typedef struct student_st

    {

       char name[10];

       int age;

    }CStudent;

    int main()

    {

       boost::pool<> student_pool(sizeof(CStudent));

       CStudent * const obj=(CStudent *)student_pool.malloc();

       student_pool.free(obj);

       return 0;

    }

        pool的模版參數只有一個分配子類型,boost提供了兩種default_user_allocator_new_delete/default_user_allocator_malloc_free,指明申請釋放內存的時候使用new/delete,還是malloc/free,默認是default_user_allocator_new_delete。構造函數有2個參數:nrequested_size,nnext_size。nrequested_size是block的大小(因為void*保存序號,因此boost內置了block的最小值,nrequested_size過小則取內置值),nnext_size是simple_segregated_storage中內存不足的時候,申請的block數量,默認是32。最全面的實例化pool類似這樣:boost::pool<boost::default_user_allocator_malloc_free> student_pool(sizeof(CStudent),255);

        pool提供的函數主要有:

    malloc/free  基于add_block/malloc/free實現,高效

     

    ordered_malloc/ordered_free  基于add_ordered_block/malloc/ordered_free實現,在pool中無任何意義,切勿使用。

     

    release_memory/purge_memory 前者釋放池中未使用內存,后者釋放池中所有內存。另池析構也會釋放內存

     

     

    2)object_pool

    對象內存池,這是最失敗的一個內存池設計。

     

    #include <boost/pool/object_pool.hpp>

     

    class A{

    public:

       A():data_(0){}

    private:

       int data_;

    };

    int main()

    {

       boost::object_pool<A> obj_pool;

       A *const pA=obj_pool.construct();

       obj_pool.destroy(pA);

       return 0;

    }

     

        object_pool繼承至pool,有兩個模版參數,第一個就是對象類型,第二個是分配子類型,默認同pool是default_user_allocator_new_delete。構造函數參數只有nnext_size,意義以及默認值同pool。最全面的實例化object_pool類似這樣:boost::pool<A,boost::default_user_allocator_malloc_free> obj_pool(255);

    object_pool提供的函數主要有(繼承至父類的略): malloc/free 復寫pool的malloc/free,add_ordered_block/malloc/ordered_free實現

    construct/destroy 基于本類的malloc/free實現,額外調用默認構造函數和默認析構函數。

    ~object_pool  單獨拿出這個說下,若析構的時候有對象未被destroy,可以檢測到,釋放內存前對其執行destroy

        為什么boost::object_pool要設計成這樣?能調用構造函數和析構函數顯然不是boost::object_pool類設計的出發點,因為構造函數只能執行默認構造函數(首次發表錯誤:可以調用任意的構造函數,參見代碼文件:boost/pool/detail/pool_construct.inc和boost/pool/detail/pool_construct_simple.inc,感謝eXile指正),近似于無,它的重點是內存釋放時候的清理工作,這個工作默認的析構函數就足夠了。apr_pool內存池中就可以注冊內存清理函數,在釋放內存的時刻執行關閉文件描述符、關閉socket等操作。boost::object_pool也想實現同樣的功能,因此設計了destroy這個函數,而同時為了防止用戶遺漏掉這個調用,而又在內存池析構的時候進行了檢測回收。為了這個目的而又不至于析構object_pool的時間復雜度是O(n平方),boost::object_pool付出了沉重的代價,在每次的destoy都執行排序功能,時間復雜度O(n),最后析構的時間復雜度是O(n),同樣為了這個目的,從simple_segregated_storage增加了add_ordered_block/ordered_free,pool增加了ordered_malloc/ordered_free等累贅多余的功能。

        基于上面討論的原因,boost::object_pool被設計成了現在的樣子,成了一個雞肋類。類的設計者似乎忘記了內存池使用的初衷,忘記了內存池中內存申請釋放的頻率很高,遠遠大于內存池對象的析構。如果你依然想使用類似于此的內存清理功能,可以在boost::object_pool上修改,不復寫malloc/free即可,重寫object_pool的析構,簡單釋放內存就好,因此析構object_pool前不要忘記調用destroy,這也是使用placement new默認遵守的規則,或者保持以前的析構函數,犧牲析構時的性能。placement new的作用是為已經申請好的內存調用構造函數,使用流程為(1)申請內存buf(2)調用placement new:new(buf)construtor()(3)調用析構destructor()(4)釋放內存buf。#include<new>可以使用placement new。

    3)singleton_pool

    pool的加鎖版本。

     

    #include <boost/pool/singleton_pool.hpp>

    typedef struct student_st

    {

       char name[10];

       int age;

    }CStudent;

    typedef struct singleton_pool_tag{}singleton_pool_tag;

    int main()

    {

       typedef boost::singleton_pool<singleton_pool_tag,sizeof(CStudent)>  global;

       CStudent * const df=(CStudent *)global::malloc();

       global::free(df);

       return 0;

    }

        singleton_pool為單例類,是對pool的加鎖封裝,適用于多線程環境,其中所有函數都是靜態類型。它的模版參數有5個,tag:標記而已,無意義;RequestedSize:block的長度;UserAllocator:分配子,默認還是default_user_allocator_new_delete;Mutex:鎖機制,默認值最終依賴于系統環境,linux下是pthread_mutex,它是對pthread_mutex_t的封裝;NextSize:內存不足的時候,申請的block數量,默認是32。最全面的使用singleton_pool類似這樣:typedef boost::singleton_pool<singleton_pool_tag,sizeof(CStudent),default_user_allocator_new_delete,details::pool::default_mutex,200> global;

        它暴露的函數和pool相同。

    4)pool_allocator/fast_pool_allocator

        stl::allocator的替換方案。兩者都是基于singleton_pool實現,實現了stl::allocator要求的接口規范。兩者的使用相同,區別在于pool_allocator的內部實現調用了ordered_malloc和ordered_free,可以滿足對大量的連續內存塊的分配請求。fast_pool_allocator 的內部實現調用了malloc和free,比較適合于一次請求單個大內存塊的情況,但也適用于通用分配,不過具有一些性能上的缺點。因此推薦使用后者。

     

    #include <boost/pool/pool_alloc.hpp>

    #include <vector>

    typedef struct student_st

    {

     char name[10];

     int age;

    }CStudent;

     

    int main()

    {

      std::vector<CStudent *,boost::fast_pool_allocator<CStudent *> > v(8);

      CStudent *pObj=new CStudent();

      v[1]=pObj;

      boost::singleton_pool<boost::fast_pool_allocator_tag,sizeof(CStudent *)>::purge_memory();

      return 0;

    }

        fast_pool_allocator的模版參數有四個:類型,分配子,鎖類型,內存不足時的申請的block數量,后三者都有默認值,不再說了。它使用的singleton_pool的tag是boost::fast_pool_allocator_tag。

    總結:boost::pool小巧高效,多多使用,多線程環境下使用boost::singleton_pool,不要使用兩者的ordered_malloc/ordered_free函數。boost::object_pool不建議使用,可以改造后使用。pool_allocator/fast_pool_allocator推薦使用后者。

     

    參考資料:

    boost官方網站:  http://www.boost.org/

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全