亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

對C++程序內存管理的精雕細琢

2019-11-17 05:48:46
字體:
來源:轉載
供稿:網友

  應用程序分配內存的方法,對程序的執行性能有著深刻的影響。目前,通用的內存分配方法本質上已非常高效,但仍有改進的空間。

  內存分配,不可一層不變

  今天,對絕大多數程序來說,通用的內存分配方法--此處指代分配算符(Allocator:即malloc或new),已達到了理想的速度及滿足了低碎片率的要求,然而,在內存分配領域,一丁點的信息都值得探討很久,某些特定程序關于分配模式的信息,將有助于實現專門的分配算符,可顯著地提高大多數高性能要求程序的性能底線。有時,當通用內存分配算符平均耗費幾百個時鐘周期時,一個良好的自定義內存分配算符可能只需要不到半打的周期。

  這就是為什么大多數高性能、高要求的應用程序(如GCC、Apache、Microsoft SQL Server),都有著它們自己的內存分配算符。也許,把這些專門的內存分配算符歸納起來,放進一個庫中,是個不錯的想法,但是,你的程序可能有不同的分配模式,其需要另外的內存分配算符,那怎么辦呢?

  等等,還有呢,假如我們設計了一種非凡用途的內存分配算符,就可以不斷發展下去,由此可從中篩選出一些,來組成一個通用目的的內存分配算符,假如此通用分配算符優于現有的通用分配算符,那么此項設計就是有效及實用的。

  下面的示例使用了Emery小組的庫--HeapLayers(http://heaplayers.org/),為了定義可配置的分配算符,其中使用了mixins(在C++社區中,也被稱為Coplien遞歸模式):通過參數化的基來定義類,每一層中只定義兩個成員函數,malloc和free:

template <class T>
strUCt Allocator : public T {
 void * malloc(size_t sz);
 void free(void* p);
 //系統相關的值
 enum { Alignment = sizeof(double) };
 //可選接口e
 size_t getSize(const void* p);
};
  在每一層的實現中,都有可能向它的基類請求內存,一般來說,一個不依靠于外界的內存分配算符,都會處在層次的頂層--直接向前請求系統的new和delete操作符、malloc和free函數。在HeapLayers的術語中,沒有頂層堆,以下是示例:

struct MallocHeap {
 void * malloc(size_t sz) {
  return std::malloc(sz);
 }
 void free(void* p) {
  return std::free(p);
 }
};
  為獲取內存,頂層堆也能通過系統調用來實現,如Unix的sbrk或mmap。getSize函數的情況就比較非凡,不是每個人都需要它,定義它只是一個可選項。但假如定義了它,你所需做的只是插入一個存儲內存塊大小的層,并提供getSize函數,見例1:

  例1:

template <class SuperHeap>
class SizeHeap {
 union freeObject {
  size_t sz;
  double _dummy; //對齊所需
 };
public:
 void * malloc(const size_t sz) {
  //添加必要的空間
  freeObject * ptr = (freeObject *)SuperHeap::malloc(sz + sizeof(freeObject));
  //存儲請求的大小
  ptr->sz = sz;
  return ptr + 1;
 }
 void free(void * ptr) {
  SuperHeap::free((freeObject *) ptr - 1);
 }
 static size_t getSize (const void * ptr) {
  return ((freeObject *)ptr - 1)->sz;
 }
};
  SizeHeap是怎樣實現一個實用的層,并掛鉤于它基類的malloc與free函數的最好示例,它在完成一些額外的工作之后,把修改好的結果返回給使用者。SizeHeap為存儲內存塊大小,分配了額外的內存,再加上適當的小心調整(指union),盡可能地避免了內存數據對齊問題。不難想像,我們可構建一個debug堆,其通過特定模式在內存塊之前或之后填充了一些字節,通過檢查是否模式已被保留,來確認內存的溢出。事實上,這正是HeapLayers的DebugHeap層所做的,非常的簡潔。

  讓我們再來看看,以上還不是最理想的狀態,某些系統已經提供了計算已分配內存塊大小的原語(此處指操作符,即前述的分配算符),在這些系統上,SizeHeap實際上只會浪費空間。在這種情況下(如Microsoft Visual C++),你將不需要SizeHeap與MallocHeap的銜接,因為MallcoHeap將會實現getSize:

struct MallocHeap {
 ... 與上相同 ...
 size_t getSize(void* p) {
  return _msize(p);
 }
};
  但似乎還有一些不足之處。想一想,我們是在統計時鐘周期,假如一個系統的malloc聲明了內存的塊大小將存儲在實際塊之前的一個字中,那將會怎樣呢?在這種情況下,SizeHeap還是會浪費空間,因為它仍會在緊接著系統已植入的塊后存儲一個字。此處所需的,只是一個用SizeHeap的方法實現了getSize的層,但未掛鉤malloc與free。這就是為什么HeapLayers把前面的SizeHeap分成了兩個,見例2:

  例2:


template <class Super>
struct UseSizeHeap : public Super {
 static size_t getSize(const void * ptr) {
  return ((freeObject *) ptr - 1)->sz;
 }
PRotected:
 union freeObject {
  size_t sz;
  double _dummy; //對齊所需
 };
};

template <class SuperHeap>
class SizeHeap: public UseSizeHeap<SuperHeap>{
 typedef typename
 UseSizeHeap<SuperHeap>::freeObject
 freeObject;
public:
 void * malloc(const size_t sz) {
  //添加必要的空間
  freeObject * ptr = (freeObject *)SuperHeap::malloc(sz + sizeof(freeObject));
  //存儲請求的大小
  ptr->sz = sz;
  return (void *) (ptr + 1);
 }
 void free(void * ptr) {
  SuperHeap::free((freeObject *)ptr - 1);
 }
};
  現在,SizeHeap就會正確地添加UseSizeHeap層,并利用它的getSize實現了,而UseSizeHeap也能通過其他配置來使用--這是一個非常優雅的設計。

  一個實用的示例:FreelistHeap

  到目前為止,我們還處于一個預備的階段,只有架構,還不知怎樣利用這些層來編寫一個高效專用的內存分配算符,也許一個比較合適的開發步驟可如下所示:

  ·收集有關程序為每種內存塊大小進行分配次數的信息。

  ·為最經常請求的大?。ㄔ诖朔Q為S),維持一個私有、逐一鏈接的列表。
 
  ·對S的內存分配盡可能地從列表中返回內存,或者從默認分配算符中返回(在分層架構中,從上級層中)。

  ·對S大小內存塊的釋放,把內存塊放回至列表中。

  ·一個精心設計的分配策略,應可對范圍大小從S1至S2,使用相同的釋放列表,并消耗同等的內存。而所需鏈接列表的操作開銷為O(1),實際上只有幾條指令。另外,指向下一條目的指針,能存儲在實際的塊中(塊中存儲了無用的數據--總為一個釋放了的塊),因此,對每個塊就不需要額外的內存了。正因為大多數應用程序分配內存的大小都是不同的,所以,對任何分配算符的實現來說,釋放列表就必不可少了。

  下面讓我們來實現一個層,由其對已知靜態范圍大小從S1至S2,實現了一個釋放列表,見例3:

  例3:

template <class Super, size_t S1, size_t S2>
struct FLHeap {
 ~FLHeap() {
  while (myFreeList) {
   freeObject* next = myFreeList->next;
   Super::free(myFreeList);
   myFreeList = next;
  }
 }
 void * malloc(const size_t s) {
  if (s < S1 s > S2)) {
   return Super::malloc(s);
  }
  if (!myFreeList) {
   return Super::malloc(S2);
  }
  void * ptr = myFreeList;
  myFreeList = myFreeList->next;
  return ptr;
 }
 void free(void * p) {
  const size_t s = getSize(p);
  if (s < S1 s > S2) {
   return Super::free(p);
  }
  freeObject p =reinterpret_cast<freeObject *>(ptr);
  p->next = myFreeList;
  myFreeList = p;
 }
private:
 // 嵌入在釋放的對象中的鏈接列表指針
 class freeObject {
  public:
   freeObject * next;
 };
 //釋放的對象鏈接列表頭
 freeObject * myFreeList;
};
  現在,你像如下所示可定義一個自定義的堆:

typedef FLHeap<
SizeHeap<MallocHeap>,
24,
32>
SmartoHeapo;
  SmartoHeapo在分配的大小在24至32之間時,速度相當快,對其它大小來說,也基本上一樣。 QQRead.com 推出數據恢復指南教程 數據恢復指南教程 數據恢復故障解析 常用數據恢復方案 硬盤數據恢復教程 數據保護方法 數據恢復軟件
專業數據恢復服務指南 原地重新分配(Inplace Resizing)

  許多的C++程序員都夢寐以求有一種標準的原語(也即操作符),用于原地重新分配內存。眾所周知,C語言中有realloc,其盡可能的原地重新分配內存,并在涉及到復制數據時使用memcpy,但memcpy并不適合于C++對象,所以,realloc也不適用于C++的對象。因此,任何一種renew原語都不能用標準C分配符來實現,這就是為什么C++中沒有renew的原因。

  以下演示了一種改進后的方法,可應用于C++代碼中的原地重新分配,請看:

const int n = 10000;
Vec v;
for (int i = 0; i < n; ++i)
v.push_back(0);
  Metrowerks的Howard Hinnant一直在為實現應用于CodeWarrior標準庫的原地擴展而努力,用他自己的話來說:

  現在有一個可進行原地重新分配的vector<T, malloc_allocator<T>>,當Vec為一個不帶原地擴展的vector<int>時,耗時為0.00095674秒;當Vec為一個帶有原地擴展的vector<int>時,耗時為0.000416943。由此可看出,內存的原地重新分配,所帶來的性能提升,非常之明顯。

  既然有了原地重新分配所帶來的好處,而堆中的每個層都能控制其自己的分配算法和數據結構,請看下面的堆層接口:

template <class T>
struct Allocator : public T {
 void * malloc(size_t sz);
 void free(void* p);
 size_t eXPand(void* p, size_t min, size_t max);
};
  擴展在語義上的意思是,嘗試通過p擴展指向在兩者之間最大尺寸的塊,并返回期望擴展的任意大小內存塊。幸運的是,一個層不必關心用于擴展的子程序,假如所有頂層的分配方法都繼續自以下的類,那么一切都將工作正常:

struct TopHeap {
 size_t expand(void*, size_t, size_t) {
  return 0;
 }

 protected:
  ~TopHeap() {}
};
  結論

  可配置的內存分配算符,是一種實用的、一體化的解決方案,可取代專門或通用的內存分配操作符。此外,HeapLayers的分層架構支持更簡單的調試,并且具有非并行的可擴展性。表1演示了一個在HeapLayers中,層實現的相關子集,其中有許多值得討論的地方,如多線程操作中的閉鎖堆、STL適配程序、各種不同的工具堆、還有怎樣結合多個層來創建一個通用的內存分配算符,另外,千萬記住不要忘了在析構函數中釋放內存,祝大家編程愉快!

  表1:部分HeapLayers庫

頂層堆 mallocHeap 取代malloc的層mmapHeap 取代虛擬內存治理的層sbrkHeap取代sbrk(連續內存)構建塊堆的層AdaptHeap使數據結構可作為堆使用BoundedFreelistHeap 有長度限制的釋放列表ChunkHeap 以給定大小的塊來治理內存CoalesceHeap 執行拼接與拆分FreelistHeap 一個釋放列表(用于捕捉釋放的對象)組合堆 HybridHeap對小對象使用一個堆,而對大對象使用另一個堆SegHeap 用于分配方法的一般分割StrictSegHeap用于分配方法的嚴格分割工具層ANSIWrapper提供與ANSI-malloc的兼容性DebugHeap檢查多種分配錯誤LockedHeap為保證線程安全的閉鎖堆PerClassHeap使用一個堆作為每個類的分配算符PHOThreadHeap帶有自有分配算符私有堆ProfileHeap 收集并輸出碎片統計ThreadHeap 一個純私有堆分配算符ExceptionHeap 當父類堆超出內存時,拋出一個異常TraceHeap 輸出有關內存分配的跟蹤信息UniqueHeap 引用一個堆對象的堆類型對象表示 CoalesceableHeap為拼接提供支持SizeHeap在頭部中記錄對象大小非凡用途的堆 ObstackHeap專門優化用于類似堆棧行為或快速大小調整的堆ZoneHeap一個區域分配算符XallocHeap 優化用于類似堆棧行為的堆通用堆KingsleyHeap快速但多碎片的堆LeaHeap 速度不快,但碎片很少的堆

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一区二区在线视频播放| 亚洲精品一区在线观看香蕉| 91成人在线观看国产| 国产欧美日韩高清| 色哟哟亚洲精品一区二区| 亚洲另类图片色| 国产精品一区二区久久久| 97在线观看视频国产| 亚洲精品久久视频| www.亚洲免费视频| 97在线视频国产| 51精品在线观看| 国产91色在线| 91在线无精精品一区二区| 亚洲国产精品成人av| 亚洲精品理论电影| 亚洲wwwav| 国产精品999| 亚洲精品福利免费在线观看| 欧美精品videos| 久久精品视频在线| 亚洲伦理中文字幕| 国产suv精品一区二区三区88区| 欧美一区二区三区……| 亚洲一区二区三区视频| 欧美日韩一区二区免费在线观看| 国产日本欧美一区二区三区| 国内精品久久久久久| 亚洲欧洲成视频免费观看| 97精品视频在线播放| 91久久久在线| 国产精品美乳一区二区免费| 日韩在线精品视频| 色综合伊人色综合网站| 亚洲国产成人精品一区二区| 国产日韩精品综合网站| 伊人伊人伊人久久| 中文字幕在线看视频国产欧美在线看完整| 欧美激情xxxxx| 亚洲成人精品在线| 国产一区在线播放| 国产精品户外野外| 最近免费中文字幕视频2019| 欧美怡红院视频一区二区三区| 国产精品444| 亚洲国产精品字幕| 97色在线观看免费视频| 欧美老肥婆性猛交视频| xxxxxxxxx欧美| 日韩一二三在线视频播| 欧美国产一区二区三区| 久久久亚洲欧洲日产国码aⅴ| 自拍偷拍亚洲一区| 茄子视频成人在线| 亚洲伊人久久综合| 久久亚洲精品毛片| 精品国产拍在线观看| 亚洲人成在线观看网站高清| 国产999精品视频| 欧美日韩在线影院| 欧美日韩国产中文精品字幕自在自线| 久久精品国产一区二区电影| 欧美日韩精品中文字幕| 久久大大胆人体| 欧美午夜片在线免费观看| 亚洲成人网av| 波霸ol色综合久久| 91高潮精品免费porn| 国产精品中文久久久久久久| 欧美成人免费大片| 97成人精品视频在线观看| 欧美激情精品久久久久久大尺度| 日韩视频免费在线观看| 亚洲国产中文字幕久久网| 亚洲精品一区中文字幕乱码| 中文字幕在线日韩| 日韩中文视频免费在线观看| 国产精品久久中文| 国产97免费视| 97人洗澡人人免费公开视频碰碰碰| 91久久在线播放| 日本成人激情视频| 国产一区二区三区在线看| 欧美丝袜一区二区三区| 欧美精品18videosex性欧美| 伊人伊成久久人综合网站| 欧美特黄级在线| 在线精品视频视频中文字幕| 日韩有码视频在线| 亚洲欧美日韩第一区| 国产成人在线一区| 中文字幕亚洲欧美在线| 中文字幕精品国产| 欧美日韩国产丝袜美女| 91爱爱小视频k| 欧美精品在线免费观看| 亚洲图片在线综合| 欧美日韩国产成人高清视频| 国内揄拍国内精品| 国产精品久久久久久久久| 91禁国产网站| 伊人久久精品视频| 国产精品成人播放| 亚洲影视九九影院在线观看| 亚洲国产成人精品久久| 夜夜躁日日躁狠狠久久88av| 欧美性感美女h网站在线观看免费| 国产精品一区电影| 成人福利在线观看| 国产亚洲欧洲高清一区| 欧美另类在线观看| 国产女人精品视频| 色噜噜亚洲精品中文字幕| 日韩中文字幕视频| 国产精品偷伦视频免费观看国产| 亚洲视频axxx| 成人性教育视频在线观看| 欧美另类69精品久久久久9999| 96国产粉嫩美女| 青青a在线精品免费观看| 国产综合在线看| 91国内揄拍国内精品对白| 97超级碰碰人国产在线观看| 日韩在线免费高清视频| 在线电影欧美日韩一区二区私密| 久久影视电视剧凤归四时歌| 中文字幕久久久| 欧美视频精品一区| 久久国产精品亚洲| 伊人成人开心激情综合网| 亚洲成人三级在线| 91超碰中文字幕久久精品| 国产精品欧美一区二区| 久久久久日韩精品久久久男男| www.久久久久久.com| 姬川优奈aav一区二区| 亚洲一区二区三区四区在线播放| 日韩中文字幕av| 中文字幕欧美精品在线| 国产亚洲精品91在线| 国产精品揄拍一区二区| 欧美激情18p| 久久91精品国产91久久跳| 亚洲伊人成综合成人网| 97人人爽人人喊人人模波多| 成人免费高清完整版在线观看| 日韩va亚洲va欧洲va国产| 日韩欧美国产成人| 日本国产精品视频| 社区色欧美激情 | 国产一区二区三区三区在线观看| 日韩精品在线免费观看| 欧美激情视频在线免费观看 欧美视频免费一| 日韩精品在线看| 一区二区国产精品视频| 久久久电影免费观看完整版| 欧美诱惑福利视频| 国产精品色午夜在线观看| 国产综合视频在线观看| 成人有码视频在线播放| 国产精品第三页| 国产成人亚洲综合91| 国产视频久久久久久久| 亚洲欧美日韩精品久久奇米色影视|