(七) 大內(nèi)存分配器

LargeObjectSpace用于保存java基礎數(shù)據(jù)類型數(shù)組或者是長字符串温算。

image.png

art虛擬機提供了兩種實現(xiàn)岗钩,要么使用LargeObjectMapSpace申眼,要么FreeListSpace谬晕。

LargeObjectMapSpace是art分配算法中最簡單的宿亡,直接匿名映射一塊內(nèi)存即可。

mirror::Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes,
                                           size_t* bytes_allocated, size_t* usable_size,
                                           size_t* bytes_tl_bulk_allocated) {
  std::string error_msg;
  MemMap mem_map = MemMap::MapAnonymous("large object space allocation",
                                        num_bytes,
                                        PROT_READ | PROT_WRITE,
                                        /*low_4gb=*/ true,
                                        &error_msg);
  mirror::Object* const obj = reinterpret_cast<mirror::Object*>(mem_map.Begin());
  const size_t allocation_size = mem_map.BaseSize();
  MutexLock mu(self, lock_);
  large_objects_.Put(obj, LargeObject {std::move(mem_map), false /* not zygote */});
 
  if (begin_ == nullptr || begin_ > reinterpret_cast<uint8_t*>(obj)) {
    begin_ = reinterpret_cast<uint8_t*>(obj);
  }
  end_ = std::max(end_, reinterpret_cast<uint8_t*>(obj) + allocation_size);

  *bytes_allocated = allocation_size;
  if (usable_size != nullptr) {
    *usable_size = allocation_size;
  }
  *bytes_tl_bulk_allocated = allocation_size;
  num_bytes_allocated_ += allocation_size;
  total_bytes_allocated_ += allocation_size;
  ++num_objects_allocated_;
  ++total_objects_allocated_;
  return obj;
}

FreeListSpace有點類似RosAlloc彪腔。會提前分配好空間侥锦。我覺得大對象還是使用LargeObjectMapSpace好點,要使用的時候再分配

創(chuàng)建

FreeListSpace* FreeListSpace::Create(const std::string& name, size_t size) {
  CHECK_EQ(size % kAlignment, 0U);
  std::string error_msg;
  MemMap mem_map = MemMap::MapAnonymous(name.c_str(),
                                        size,
                                        PROT_READ | PROT_WRITE,
                                        /*low_4gb=*/ true,
                                        &error_msg);
  return new FreeListSpace(name, std::move(mem_map), mem_map.Begin(), mem_map.End());
}

FreeListSpace::FreeListSpace(const std::string& name,
                             MemMap&& mem_map,
                             uint8_t* begin,
                             uint8_t* end)
    : LargeObjectSpace(name, begin, end, "free list space lock"),
      mem_map_(std::move(mem_map)) {
  const size_t space_capacity = end - begin;
  free_end_ = space_capacity;
  CHECK_ALIGNED(space_capacity, kAlignment);
  const size_t alloc_info_size = sizeof(AllocationInfo) * (space_capacity / kAlignment);
  std::string error_msg;
  allocation_info_map_ =
      MemMap::MapAnonymous("large object free list space allocation info map",
                           alloc_info_size,
                           PROT_READ | PROT_WRITE,
                           /*low_4gb=*/ false,
                           &error_msg);
  CHECK(allocation_info_map_.IsValid()) << "Failed to allocate allocation info map" << error_msg;
  allocation_info_ = reinterpret_cast<AllocationInfo*>(allocation_info_map_.Begin());
}


allocation_info_保存每頁的使用信息德挣。分配算法有點類似RosAlloc的Run分配恭垦,但更簡單些。從可用的空間切割出來可使用的格嗅。


mirror::Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
                                     size_t* usable_size, size_t* bytes_tl_bulk_allocated) {
  MutexLock mu(self, lock_);
  const size_t allocation_size = RoundUp(num_bytes, kAlignment);
  AllocationInfo temp_info;
  temp_info.SetPrevFreeBytes(allocation_size);
  temp_info.SetByteSize(0, false);
  AllocationInfo* new_info;
  // Find the smallest chunk at least num_bytes in size.
  auto it = free_blocks_.lower_bound(&temp_info);
  if (it != free_blocks_.end()) {
    AllocationInfo* info = *it;
    free_blocks_.erase(it);
    // Fit our object in the previous allocation info free space.
    new_info = info->GetPrevFreeInfo();
    // Remove the newly allocated block from the info and update the prev_free_.
    info->SetPrevFreeBytes(info->GetPrevFreeBytes() - allocation_size);
    if (info->GetPrevFreeBytes() > 0) {
      AllocationInfo* new_free = info - info->GetPrevFree();
      new_free->SetPrevFreeBytes(0);
      new_free->SetByteSize(info->GetPrevFreeBytes(), true);
      // If there is remaining space, insert back into the free set.
      free_blocks_.insert(info);
    }
  } else {
    // Try to steal some memory from the free space at the end of the space.
    if (LIKELY(free_end_ >= allocation_size)) {
      // Fit our object at the start of the end free block.
      new_info = GetAllocationInfoForAddress(reinterpret_cast<uintptr_t>(End()) - free_end_);
      free_end_ -= allocation_size;
    } else {
      return nullptr;
    }
  }
  *bytes_allocated = allocation_size;
  if (usable_size != nullptr) {
    *usable_size = allocation_size;
  }
  DCHECK(bytes_tl_bulk_allocated != nullptr);
  *bytes_tl_bulk_allocated = allocation_size;
  // Need to do these inside of the lock.
  ++num_objects_allocated_;
  ++total_objects_allocated_;
  num_bytes_allocated_ += allocation_size;
  total_bytes_allocated_ += allocation_size;
  mirror::Object* obj = reinterpret_cast<mirror::Object*>(GetAddressForAllocationInfo(new_info));

  new_info->SetPrevFreeBytes(0);
  new_info->SetByteSize(allocation_size, false);
  return obj;
}


FreeListSpace適合頻繁申請然后又回收的大內(nèi)存對象的應用場景番挺。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屯掖,隨后出現(xiàn)的幾起案子建芙,更是在濱河造成了極大的恐慌,老刑警劉巖懂扼,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禁荸,死亡現(xiàn)場離奇詭異,居然都是意外死亡阀湿,警方通過查閱死者的電腦和手機赶熟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陷嘴,“玉大人映砖,你說我怎么就攤上這事≡职ぃ” “怎么了邑退?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長劳澄。 經(jīng)常有香客問我地技,道長,這世上最難降的妖魔是什么秒拔? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任莫矗,我火速辦了婚禮,結果婚禮上砂缩,老公的妹妹穿的比我還像新娘作谚。我一直安慰自己,他們只是感情好庵芭,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布妹懒。 她就那樣靜靜地躺著,像睡著了一般双吆。 火紅的嫁衣襯著肌膚如雪眨唬。 梳的紋絲不亂的頭發(fā)上滔悉,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音单绑,去河邊找鬼回官。 笑死,一個胖子當著我的面吹牛搂橙,可吹牛的內(nèi)容都是我干的歉提。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼区转,長吁一口氣:“原來是場噩夢啊……” “哼苔巨!你這毒婦竟也來了?” 一聲冷哼從身側響起废离,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤侄泽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜻韭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悼尾,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年肖方,在試婚紗的時候發(fā)現(xiàn)自己被綠了闺魏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡俯画,死狀恐怖析桥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情艰垂,我是刑警寧澤泡仗,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站猜憎,受9級特大地震影響娩怎,放射性物質發(fā)生泄漏。R本人自食惡果不足惜拉宗,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一峦树、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧旦事,春花似錦、人聲如沸急灭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葬馋。三九已至卖鲤,卻和暖如春肾扰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛋逾。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工集晚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人区匣。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓偷拔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亏钩。 傳聞我的和親對象是個殘疾皇子莲绰,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容