Node:Buffer

六、Buffer

1. Buffer结构

1.1 模块结构
  • buffer的性能相关部分用C++实现,非性能部分用JavaScript实现;
  • Node在进程启动时就已经加载了,并将其放在全局对象。
1.2 Buffer对象
  • Buffer类似与数组,他的元素未16进制两位数。
  • 不同编码所占的元素个数不相同,UTF8编码下一个中文字符占三个元素,字母和半角标点占一个字符。
  • 可以通过buffer.length来获取Buffer对象的长度。
  • 如果给Buffer元素赋值0-255以外的值,Buffer就会对其连续加上256,直到得到区间内的值为止;
  • 若赋值小数,则会舍弃小数部分。
1.3 Buffer内存分配
  • Buffer对象的内存分配不是在V8的堆内存,而是Node在C++层面上实现内存的申请;

  • Node在内存上的使用应用的策略是:在C++层面申请内存,在Javascript层面分配内存;

  • Node采用了slab分配机制,用于高效地分配内存;

  • slab就是一块已经申请好的固定大小的内存区域,具有三种状态:

    full:完全分配状态;

    partial:部分分配状态;

    empty:没有分配状态。

  • 当我们需要一个Buffer对象,可以通过new Buffer(size)的方式来分配指定大小的对象;

  • 而Node以8KB来界定Buffer对象的大小:

    Buffer.poolSize = 8 * 1024

    这个8KB就是slab的值,在JavaScript层面,以它为单位进行内存分配。

1.4 分配小Buffer对象
  • 若指定的Buffer对象大小小于8KB,则Node会按照小对象的方式进行分配:

    1. Buffer在分配过程中主要使用一个局部变量pool作为中间处理对象,处于分配状态的slab都指向它:

      var pool;
      function allocPool() {
             
          pool = new SlowBuffer(Buffer.poolSize);
          pool.used = 0;
      }
      

      此时,slab处于empty状态。

    2. 构造小Buffer对象时,Node会去检查有没有Pool对象,如果没有被创建,将会创建一个新的slab并指向它:

      if(!pool || pool.length - pool.used < this.length) {
             
          allocPool();
      }
      
    3. 当前的Buffer对象的parent属性也指向这个slab,并记录下是从这个slab的哪个位置开始使用的,slab自身的used也需要记录使用了多少字节:

      this.parent = pool;
      this.offset = pool.used;
      pool.used += this.length;
      // 如果used超过了8KB
      if(pool.used & 7) {
             
          pool.used = (pool.used + 8) & ~7;
      }
      
    4. 当再次创建一个Buffer对象的时候,构造过程中会判断这个slab的剩余空间是否足够。

      如果够,直接使用剩余的空间并分配slab的分配状态;

      如果slab的空间不够了,将会构造新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值