青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator?

peakflys原創(chuàng)作品,轉(zhuǎn)載請(qǐng)保留原作者和源鏈接
   項(xiàng)目中和自己代碼中大量使用了STL的容器,平時(shí)也沒(méi)怎么關(guān)注alloc的具體實(shí)現(xiàn)細(xì)節(jié),主觀(guān)認(rèn)識(shí)上還停留在侯捷大師的《STL源碼剖析》中的講解。
   以下為書(shū)中摘錄截圖:詳見(jiàn)書(shū)中2.2.4節(jié)內(nèi)容

前段時(shí)間項(xiàng)目中出了一個(gè)內(nèi)存問(wèn)題,在追查問(wèn)題的過(guò)程中查看了對(duì)應(yīng)的源碼(版本為libstdc++-devel-4.1.2)
源碼文件c++allocator.h中定義了默認(rèn)的Alloc:#ifndef _CXX_ALLOCATOR_H
#define _CXX_ALLOCATOR_H 1

// Define new_allocator as the base class to std::allocator.
#include <ext/new_allocator.h>
#define __glibcxx_base_allocator  __gnu_cxx::new_allocator

#endif
查看new_allocator.h文件,發(fā)現(xiàn)new_allocator僅僅是對(duì)operator new和operator delete的簡(jiǎn)單封裝(感興趣的朋友可自行查看)。
眾所周知libstdc++中STL的大部分實(shí)現(xiàn)是取自SGI的STL,而《STL源碼剖析》的源碼是Cygnus C++ 2.91則是SGI STL的早期版本,下載源碼看了一下allocator的實(shí)現(xiàn)確實(shí)如書(shū)中所言。
不知道從哪個(gè)版本起,SGI的STL把默認(rèn)的Alloc替換成了new_allocator,有興趣的同學(xué)可以查一下。
知道結(jié)果后,可能很多人和我一樣都不禁要問(wèn):Why?
以下是兩個(gè)版本的源碼實(shí)現(xiàn):
1、new_allocator
      // NB: __n is permitted to be 0.  The C++ standard says nothing
      
// about what the return value is when __n == 0.
      pointer
      allocate(size_type __n, const void* = 0)
      {
    if (__builtin_expect(__n > this->max_size(), false))
      std::__throw_bad_alloc();

    return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
      deallocate(pointer __p, size_type)
      { ::operator delete(__p); }
2、__pool_alloc
  template<typename _Tp>
    _Tp*
    __pool_alloc<_Tp>::allocate(size_type __n, const void*)
    {
      pointer __ret = 0;
      if (__builtin_expect(__n != 0, true))
    {
      if (__builtin_expect(__n > this->max_size(), false))
        std::__throw_bad_alloc();

      // If there is a race through here, assume answer from getenv
      
// will resolve in same direction.  Inspired by techniques
      
// to efficiently support threading found in basic_string.h.
      if (_S_force_new == 0)
        {
          if (getenv("GLIBCXX_FORCE_NEW"))
        __atomic_add(&_S_force_new, 1);
          else
        __atomic_add(&_S_force_new, -1);
        }

      const size_t __bytes = __n * sizeof(_Tp);
      if (__bytes > size_t(_S_max_bytes) || _S_force_new == 1)
        __ret = static_cast<_Tp*>(::operator new(__bytes));
      else
        {
          _Obj* volatile* __free_list = _M_get_free_list(__bytes);

          lock sentry(_M_get_mutex());
          _Obj* __restrict__ __result = *__free_list;
          if (__builtin_expect(__result == 0, 0))
        __ret = static_cast<_Tp*>(_M_refill(_M_round_up(__bytes)));
          else
        {
          *__free_list = __result->_M_free_list_link;
          __ret = reinterpret_cast<_Tp*>(__result);
        }
          if (__builtin_expect(__ret == 0, 0))
        std::__throw_bad_alloc();
        }
    }
      return __ret;
    }
  template<typename _Tp>
    void
    __pool_alloc<_Tp>::deallocate(pointer __p, size_type __n)
    {
      if (__builtin_expect(__n != 0 && __p != 0, true))
    {
      const size_t __bytes = __n * sizeof(_Tp);
      if (__bytes > static_cast<size_t>(_S_max_bytes) || _S_force_new == 1)
        ::operator delete(__p);
      else
        {
          _Obj* volatile* __free_list = _M_get_free_list(__bytes);
          _Obj* __q = reinterpret_cast<_Obj*>(__p);

          lock sentry(_M_get_mutex());
          __q ->_M_free_list_link = *__free_list;
          *__free_list = __q;
        }
    }
    }
從源碼中可以看出new_allocator基本就沒(méi)有什么實(shí)現(xiàn),僅僅是對(duì)operator new和operator delete的封裝,而__pool_alloc的實(shí)現(xiàn)基本和《STL源碼剖析》中一樣,所不同的是加入了多線(xiàn)程的支持和強(qiáng)制operator new的判斷。
無(wú)論從源碼來(lái)看,還是實(shí)際的測(cè)試(后續(xù)會(huì)附上我的測(cè)試版本),都可以看出__pool_alloc比new_allocator更勝一籌。

同很多人討論都不得其解,網(wǎng)上也很少有關(guān)注這個(gè)問(wèn)題的文章和討論,倒是libstdc++的官網(wǎng)文檔有這么一段:
(peakflys注:文檔地址:https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#allocator.default)
從文檔的意思來(lái)看,選擇new_allocator是基于大量測(cè)試,不幸的是文檔中鏈接的測(cè)試?yán)泳鶡o(wú)法訪(fǎng)問(wèn)到……不過(guò)既然他們說(shuō)基于測(cè)試得出的結(jié)果,我就隨手寫(xiě)了一個(gè)自己的例子:
#include <map>
#include <vector>
#ifdef _POOL
#include <ext/pool_allocator.h>
#endif

static const unsigned int Count = 1000000;

using namespace std;

struct Data
{
    int a;
    double b;
};

int main()
{
#ifdef _POOL
    map<int, Data, less<int>, __gnu_cxx::__pool_alloc<pair<int, Data> > > mi;
    vector<Data, __gnu_cxx::__pool_alloc<Data> > vi;
#else
    map<int, Data> mi;
    vector<Data> vi;
#endif

    for(int i = 0; i < Count; ++i)
    {
        Data d;
        d.a = i;
        d.b = i * i;
        mi[i] = d;
        vi.push_back(d);
    }
    mi.clear();
#ifdef _POOL
    vector<Data, __gnu_cxx::__pool_alloc<Data> >().swap(vi);
#else
    vector<Data>().swap(vi);
#endif
    for(int i = 0; i < Count; ++i)
    {
        Data d;
        d.a = i;
        d.b = i * i;
        mi[i] = d;
        vi.push_back(d);
    }
    return 0;
}
因?yàn)楫?dāng)數(shù)據(jù)大于128K時(shí),__pool_alloc同new_allocator一樣直接調(diào)用operator,所以例子中構(gòu)造出的Data小于128K,來(lái)模擬兩個(gè)分配器的不同。同時(shí)如libstdc++官網(wǎng)中說(shuō)的,我們同時(shí)使用了sequence容器vector和associate容器map。
例子中模擬了兩種類(lèi)型容器的插入-刪除-插入的過(guò)程,同時(shí)里面包含了元素的構(gòu)造、析構(gòu)以及內(nèi)存的分配和回收。
以下是在我本地機(jī)器上運(yùn)行的結(jié)果:
1、-O0的版本:

2、-O2的版本:

多線(xiàn)程的測(cè)試?yán)游揖筒毁N了,測(cè)試結(jié)果大致和上面相同,大家可以自行測(cè)試。
從多次運(yùn)行的結(jié)果來(lái)看__pool_alloc的性能始終是優(yōu)于new_allocator的。
又回到那個(gè)問(wèn)題,為什么SGI STL的官方把默認(rèn)的Alloc從__pool_alloc變?yōu)閚ew_allocator。
本篇文章不能給大家一個(gè)答案,官方網(wǎng)站上也未看到解釋?zhuān)约何ㄒ豢赡艿牟聹y(cè)是
1、__pool_alloc不利于使用者自定義operator new和operator delete(其實(shí)這條理由又被我自己推翻了,因?yàn)橥ㄟ^(guò)源碼可以知道置位_S_force_new即可解決)
2、malloc性能的提升以及硬件的更新導(dǎo)致使用默認(rèn)的operator new即可。

如果大家有更好,更權(quán)威的答案請(qǐng)告訴我(peakflys@gmail.com)或者留言,謝謝。
                                                                  by peakflys 16:49:49 Wednesday, January 14, 2015

posted on 2015-01-14 16:50 peakflys 閱讀(4440) 評(píng)論(8)  編輯 收藏 引用 所屬分類(lèi): C++

評(píng)論

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-15 00:12 egmkang

跟硬件沒(méi)關(guān)系,malloc性能提升.因?yàn)閙alloc本身在thread上面就有一個(gè)pool.
而且高性能的分配器越來(lái)越多,比如tcmalloc/jemalloc,已經(jīng)沒(méi)有任何必要再提供一個(gè)pool allocator  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-15 09:12 蘋(píng)果汁

樓主好學(xué) 贊一個(gè)  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator?[未登錄](méi) 2015-01-15 13:01 chipset

pool不拼接內(nèi)存,一塊大內(nèi)存被分割成很多相等的小塊,此時(shí)調(diào)用分配一塊較大內(nèi)存可能失敗,不是因?yàn)閮?nèi)存不夠用,而是因?yàn)槿欠指畛尚∷閴K不拼接導(dǎo)致的。這是Pool的致命傷。再者Pool的效率也高不到哪里,以不拼接小塊換速度的做法不值得提倡。  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-15 17:42 xxoo

樓上的,內(nèi)存池的作用不就是這個(gè)嗎?你申請(qǐng)一塊內(nèi)存,可以做到物理不連續(xù)?  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-15 19:23 peakflys

如果我沒(méi)記錯(cuò)的話(huà)malloc自始至終都有自己的一套pool策略,所以我所說(shuō)的malloc性能提升并非指的這個(gè)。
不過(guò)第三方穩(wěn)定高效的allocator實(shí)現(xiàn)可能是標(biāo)準(zhǔn)庫(kù)作者放棄pool的一個(gè)原因@egmkang
  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-15 19:31 peakflys

說(shuō)的不錯(cuò),pool的方式存在的問(wèn)題是挺多。不過(guò)對(duì)于pool的效率高不到哪去的觀(guān)點(diǎn)我不敢認(rèn)同,針對(duì)大量小數(shù)據(jù)的分配,有時(shí)候還必須得使用pool的方式,不然ptmalloc、tcmalloc、jemalloc等不會(huì)維護(hù)復(fù)雜的內(nèi)存分配方式@chipset  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator? 2015-01-20 15:24 juegoskizi

我很喜歡,很不錯(cuò)的職位。  回復(fù)  更多評(píng)論   

# re: SGI STL中默認(rèn)Allocator為何變?yōu)閚ew_allocator?[未登錄](méi) 2016-03-07 14:09 JAKE

樓主,有個(gè)問(wèn)題請(qǐng)教下:
我有個(gè)應(yīng)用場(chǎng)景,即線(xiàn)程A使用obj_pool分配了一個(gè)對(duì)象obj,線(xiàn)程B用完obj后歸還給pool。 這里肯定會(huì)有線(xiàn)程同步隱患。

目前我使用兩個(gè)lockfree隊(duì)列完美解決這個(gè)問(wèn)題,但很繁瑣。

我想問(wèn)的是
使用tcmalloc的話(huà),能解決我上邊所說(shuō)的問(wèn)題嗎?  回復(fù)  更多評(píng)論   

<2012年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

導(dǎo)航

統(tǒng)計(jì)

公告

人不淡定的時(shí)候,就愛(ài)表現(xiàn)出來(lái),敲代碼如此,偶爾的靈感亦如此……

常用鏈接

留言簿(4)

隨筆分類(lèi)

隨筆檔案

文章檔案

搜索

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲理论在线观看| 午夜伦理片一区| 黑人一区二区| 国产精品99久久久久久久vr | 欧美日韩在线精品| 另类欧美日韩国产在线| 国产精品一区二区黑丝| 中国女人久久久| 亚洲视频观看| 欧美日韩不卡合集视频| 欧美激情亚洲视频| 亚洲国产高清在线| 久久永久免费| 欧美成人精品不卡视频在线观看| 国产欧美亚洲视频| 亚洲在线观看视频| 午夜日本精品| 国产区亚洲区欧美区| 亚洲女人天堂av| 久久国产精品毛片| 国产主播精品| 久久香蕉精品| 久久av红桃一区二区小说| 欧美专区日韩专区| 国产偷自视频区视频一区二区| 亚洲视频第一页| 午夜在线观看欧美| 国产亚洲激情在线| 久久激情网站| 欧美成熟视频| 亚洲麻豆国产自偷在线| 牛夜精品久久久久久久99黑人| 亚洲福利视频二区| 中日韩在线视频| 国产精品高潮粉嫩av| 先锋影音网一区二区| 巨乳诱惑日韩免费av| 亚洲人成网站色ww在线| 欧美日韩中文字幕在线| 亚洲午夜日本在线观看| 久久久水蜜桃av免费网站| 91久久国产综合久久蜜月精品| 欧美交受高潮1| 亚洲制服少妇| 欧美91大片| 亚洲午夜一二三区视频| 国产揄拍国内精品对白| 欧美成人有码| 亚洲专区免费| 欧美成人a视频| 亚洲一二三区视频在线观看| 国产原创一区二区| 欧美激情亚洲一区| 性欧美大战久久久久久久久| 亚洲国产精品va在线看黑人| 午夜精品视频在线观看| 亚洲第一免费播放区| 欧美色图五月天| 久久精品中文字幕免费mv| 亚洲精品国产精品乱码不99按摩| 午夜精品久久久久久久99樱桃 | 欧美成人性网| 亚洲欧美在线磁力| 亚洲国产精品精华液2区45| 欧美日本三区| 久久久久免费| 亚洲一级黄色片| 亚洲二区三区四区| 久久久久久网站| 亚洲视屏在线播放| 亚洲电影自拍| 国产日韩欧美亚洲一区| 欧美日韩国产探花| 免费一区视频| 欧美资源在线| 亚洲图片自拍偷拍| 亚洲精品视频在线播放| 蜜桃久久av| 欧美一区二区啪啪| 亚洲午夜精品久久久久久浪潮 | 在线综合亚洲欧美在线视频| 欧美激情精品久久久久久免费印度| 性色av一区二区怡红| 一本色道久久综合一区| 亚洲国产精品久久久久婷婷老年| 国产精品视频网| 欧美性淫爽ww久久久久无| 欧美激情一二区| 欧美成人免费小视频| 久久综合九色| 揄拍成人国产精品视频| 亚洲第一毛片| 国产欧美韩日| 国产精品国产一区二区| 欧美视频在线观看 亚洲欧| 女同性一区二区三区人了人一 | 亚洲国产二区| 亚洲第一页自拍| 亚洲福利视频网| 在线看国产一区| 在线精品视频一区二区三四| 永久555www成人免费| 永久免费视频成人| 在线观看欧美亚洲| 在线看一区二区| 亚洲国产精品成人久久综合一区| 永久免费精品影视网站| 亚洲激情欧美| 亚洲另类在线视频| 一区二区三区高清视频在线观看| 99这里只有久久精品视频| 夜夜嗨av一区二区三区网站四季av| 亚洲日本中文字幕区| 99国产精品久久| 日韩图片一区| 亚洲女女做受ⅹxx高潮| 欧美一区二区国产| 久久伊人亚洲| 欧美激情精品久久久久久蜜臀 | 激情亚洲网站| 亚洲高清资源| 亚洲视频一起| 久久精品人人做人人爽电影蜜月| 美脚丝袜一区二区三区在线观看| 欧美成人首页| 一区二区三区精品国产| 香蕉久久国产| 欧美gay视频激情| 欧美日韩一区二区三区视频| 国产欧美二区| 亚洲精品一级| 午夜久久黄色| 欧美91视频| 中日韩视频在线观看| 久久激情综合| 欧美另类高清视频在线| 国产日韩一级二级三级| 亚洲黄色影片| 欧美亚洲专区| 欧美激情一区二区久久久| 夜夜嗨av一区二区三区中文字幕| 欧美一级成年大片在线观看| 美女91精品| 国产精品任我爽爆在线播放| 在线观看免费视频综合| 亚洲欧美美女| 欧美激情视频网站| 先锋影音久久| 欧美三区美女| 91久久久久| 久久精品一区二区三区中文字幕 | 欧美伊人久久| 欧美婷婷久久| 亚洲三级网站| 久久婷婷麻豆| 亚洲一区二区三区视频播放| 男女激情久久| 国产在线视频欧美一区二区三区| 在线一区二区三区做爰视频网站| 浪潮色综合久久天堂| 亚洲午夜91| 欧美日韩精品免费观看视一区二区| 激情国产一区| 久久国产夜色精品鲁鲁99| 9l国产精品久久久久麻豆| 欧美成年人视频网站| 国产一二三精品| 欧美激情在线观看| 国产亚洲精品久久久久动| 亚洲图片欧洲图片av| 亚洲第一精品影视| 欧美一区二区黄| 国产欧美1区2区3区| 亚洲综合二区| 一本久久综合亚洲鲁鲁五月天| 欧美成人国产一区二区| 亚洲国产成人久久综合一区| 久久久亚洲午夜电影| 先锋资源久久| 国产日韩欧美一区二区| 欧美怡红院视频| 亚洲欧美精品在线| 国产精品区二区三区日本| 亚洲一区免费观看| 99精品99| 国产精品v日韩精品v欧美精品网站| 日韩一级欧洲| 亚洲久色影视| 国产精品成人一区二区三区吃奶 | 欧美国产1区2区| 亚洲精品无人区| 91久久综合亚洲鲁鲁五月天| 欧美高清免费| 日韩视频―中文字幕| 亚洲人成网站999久久久综合 | 欧美福利一区二区三区| 日韩午夜av在线| 一本色道久久综合亚洲精品小说 | 夜夜嗨av一区二区三区网页| 日韩午夜中文字幕|