首页 > 其他分享 >【LevelDB】【utils】Arena类解析

【LevelDB】【utils】Arena类解析

时间:2023-12-13 22:15:49浏览次数:31  
标签:Arena alloc LevelDB utils bytes 内存 block size

Arena类

  Arena类是极为简易的内存池实现,支持动态申请内存空间(内存对齐/不对齐方式),通过RAII机制保证Arena对象管理的内存在Arena对象生命周期结束后自动清理。

  源文件位置

    util/arena.h

    util/arena.cc

  优点:访问速度快

  缺点:存在内存浪费,详细见下文AllocateFallback接口分析;不支持Deallocate操作,不适合作为常驻内存池使用;不当的访问Allocate/AllocateAligned申请的内存将导致预期外的错误

公共接口

char* Allocate(size_t bytes); // 从Arena中申请指定大小的内存块
char* AllocateAligned(size_t bytes); // 从Arena中申请指定大小的内存块(内存对齐)
size_t MemoryUsage() const // 获取内存使用率;

私有接口

char* AllocateFallback(size_t bytes); // 在Arena剩余的已申请的内存空间不足时用于申请新的内存块
char* AllocateNewBlock(size_t block_bytes); // 调用new申请block_bytes大小的内存并更新blocks_及memory_usage_

私有成员变量

char* alloc_ptr_; // 当前block内空闲内存的起始地址
size_t alloc_bytes_remaining_; // 当前block内空闲内存大小
std::vector<char*> blocks_; // 申请的所有内存块,由vecotr进行管理
std::atomic<size_t> memory_usage_; // Arena内存使用率

构造函数/析构函数

Arena(); // 初始化各成员变量,初始的Arena是空的,并不像常见的内存池实现中会预申请指定大小的内存块
~Arena(); // 释放所有申请的内存块

关键接口

char* AllocateFallback(size_t bytes);

实现思想:

  申请的内存超出4096字节时,直接分配新的block给使用者,不改变alloc_ptr_及alloc_bytes_remaining指向,避免浪费内存

  申请的内存低于1024字节时,将申请新的4096字节大小的block,此时将会放弃原block中剩余的内存(因为alloc_ptr以及alloc_bytes_remaining将会指向新的block)

源码(注释版):

char* Arena::AllocateFallback(size_t bytes) {
  // 若bytes大于1024字节时,恰好申请bytes字节大小的block并将此block作为结果返回
  // 此时Arena的alloc_ptr_及alloc_bytes_remaining_仍指向的具有剩余空间的block,从而避免内存浪费
  if (bytes > kBlockSize / 4) {
    // Object is more than a quarter of our block size.  Allocate it separately
    // to avoid wasting too much space in leftover bytes.
    char* result = AllocateNewBlock(bytes);
    return result;
  }

  // 直接申请4096字节大小的block,此时将会放弃原block中剩余的内存(因为alloc_ptr_以及alloc_bytes_remaining_将会指向新的block)
  // We waste the remaining space in the current block.
  alloc_ptr_ = AllocateNewBlock(kBlockSize);
  alloc_bytes_remaining_ = kBlockSize;

  // 从新的block中分配bytes大小的空间
  char* result = alloc_ptr_;
  alloc_ptr_ += bytes;
  alloc_bytes_remaining_ -= bytes;
  return result;
}
char* AllocateAligned(size_t bytes); 实现思想:   以内存对齐的方式申请内存,除去计算内存对齐需补齐的slop外逻辑与Allocate等同 源码(注释版):
char* Arena::AllocateAligned(size_t bytes) {
  // 获取环境上应以多少位进行字节对齐(最低为8字节对齐)
  const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
  // 指针大小必须为2的幂,以8字节对齐为例(即align为8),1000 & 0111结果为0
  // 若align非2的幂值,由于align、align - 1的最高位非0的最高位必然相同,因此两者结果必定不为0,(以align为9为例),1001 & 1000结果为8
  static_assert((align & (align - 1)) == 0,
                "Pointer size should be a power of 2");
  // 计算当前alloc_ptr_指向的地址若按align对齐,有多少字节是不满足对齐要求的,类似reinterpret_cast<uintptr_t>(alloc_ptr_) % align
  // 因此为了字节对齐,需要额外补充align - current_mod字节
  size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1);
  size_t slop = (current_mod == 0 ? 0 : align - current_mod);
  size_t needed = bytes + slop; // 总共所需申请的内存大小
  char* result;
  // 若剩余的已申请的内存空间可满足要求,则直接在已申请的内存上分配
  if (needed <= alloc_bytes_remaining_) {
    result = alloc_ptr_ + slop;
    alloc_ptr_ += needed;
    alloc_bytes_remaining_ -= needed;
  } else {
    // 剩余的已申请的内存空间不满足要求,则新申请内存块
    // AllocateFallback always returned aligned memory
    result = AllocateFallback(bytes);
  }
  // 保证由上述计算后申请的内存起始地址必然是内存对齐的
  assert((reinterpret_cast<uintptr_t>(result) & (align - 1)) == 0);
  return result;
}

 

标签:Arena,alloc,LevelDB,utils,bytes,内存,block,size
From: https://www.cnblogs.com/pond-flower/p/17900043.html

相关文章

  • 将第2层数据中的数组对象中的ts属性、value属性遍历单独存放到一个新数组中xData、yDa
          ......
  • vitest&@vue/test-utils组件单元测试
    依赖"vitest":"0.34.6","@vue/test-utils":"2.4.3","axios-mock-adapter":"^1.22.0",示例import{mount}from"@vue/test-utils";import{test,vi}from"vitest";import{gl......
  • Springboot内置神器:CollectionUtils工具类的实战秘籍
    前言实际业务开发中,集合的判断和操作也是经常用到的,Spring也针对集合的判断和操作封装了一些方法,但是最令我惊讶的是,我在梳理这些内容的过程中发现了一些有趣的现象,我的第一反应是不敢相信,再想一想,没错,我是对的。所以强烈建议大家可以认真看完这篇文章,这一篇绝对有价值,因为有趣的......
  • Spring Boot中的StringUtils:强大的工具类解析
    在实际的业务开发中,除了经常有针对对象的判断或操作以外,经常也会遇到的就是字符串的判断和操作。比如判断字符串是否为空、是否以某个字符结尾、去除头部和尾部的空白字符、字符的查找和替换。在Spring的核心包中存在这样一个类org.springframework.util.StringUtils,它提供了常见的......
  • JSON utils 工具类核心方法parseObject , toString实现
    1packagecom.ls.utils;23importjava.lang.reflect.Array;4importjava.lang.reflect.Field;5importjava.util.Arrays;67/**8*@authorLartimes9*@version1.010*@description:JSON工具类11*toJSONString12*parseObject13......
  • vue中引用utils中的方法
    utils中的目录解构如下(utils在src目录下),以深拷贝为例:deepClone文件的代码如下:functiondeepClone(substance){if(typeofsubstance!=='object'||substance==null){returnsubstance;}constresult=Array.isArray(substance)?[]:{};for(constkey......
  • XLSX.utils 下的 Api
    工作表aoa_to_sheet将JS数据数组转换为工作表json_to_sheet将JS对象数组转换为工作表table_to_sheet将DOM表元素转换为工作表sheet_add_aoa将JS数据数组添加到现有工作表中sheet_add_json将JS对象数组添加到现有工作表中sheet_add_dom将DOM表元素中的数......
  • apache集合工具类ListUtils
    <dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency>判断两集合是否相等List<String>list1=Arrays.asList("1&qu......
  • JacksonUtils - 封装基于 jackson 的 json 转换逻辑代码
    JacksonUtils.javapackageorg.example.util;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.JavaType;importcom.fasterxml.jackson.databind.JsonNode;importcom.fasterxml.jackson.databind.ObjectMapper;im......
  • apache的对象工具类ObjectUtils
    org.apache.commons.lang3.ObjectUtils主要是Apache提供的对对象进行操作的工具类。它会使代码变得更加优雅。判断对象是否为空booleanisEmpty=ObjectUtils.isEmpty(newPerson());//输出:falsebooleanisEmpty=ObjectUtils.isEmpty(null);//输出:true检查元素是否为空/......