当前位置: 首页 > 工具软件 > Go Buffer > 使用案例 >

理解Buffer

汪臻
2023-12-01

1.Buffer结构

Buffer是一个像Array的对象,主要用于操作字节

在Node进程启动时就已经加载Buffer,并将其放在全局对象上;无须通过require加载

2.Buffer对象

Buffer对象类似于数组,元素为16进制的两位数,即0~255的数值

  • length获取长度 、下标访问元素

3.Buffer内存分配

Buffer对象的内存分配不是在V8的堆内存中,而是在Node的C++层面实现内存申请

Node采用slab分配机制,slab是一种动态内存管理机制,有三种状态:

  1. full:完全分配
  2. partial:部分
  3. empry:没有分配

指定大小的Buffer对象:new Buffer(size)
Node以8K为界限来区分Buffer是大对象还是小对象

  • 分配小对象
    使用一个局部变量pool作为中间处理对象,处于分配状态的slab单元指向它
var pool
function allocPool(){
	pool = new SlowBuffer(Buffer.poolSize)
	pool.used=0
	}


  • 分配大对象
    直接分配一个SlowBuffer对象作为slab单元
this.parent = new SlowBuffer(this.length)
this.offset = 0

4.Buffer转换

  • 字符串转Buffer
new Buffer(str,encoding)
  • Buffer转字符串
buf.toString(encoding,start,end)
  • Buffer拼接
    Buffer在使用场景中,通常以一段一段的方式传输。
    实例:从输入流中读取内容
var fs = require('fs')

var rs = fs.createReadStream('./Node/input.txt')
var data = ''
// chunk对象即是Buffer对象
rs.on('data', function(chunk) {
    data += chunk // 隐藏了toString方法
    // data = data.toString()+chunk.toString()
    
})
rs.on('end', function() {
    console.log(data)
})
  • 中文乱码问题
  1. 设置编码方式setEncoding()
    在调用setEncoding()时,可读流对象在内部会设置decoder对象;目前只能处理utf8、Base64、UCS-2三种编码
  2. 正确拼接Buffer:concat方法
    用数组存储接收到的所有Buffer片段并记录下所有片段的总长度,然后调用Buffer.concat()方法生成一个合并的Buffer对象

5.Buffer与性能

在网络中,通常需要转换为Buffer,以二进制数据传输;提高字符串到Buffer的转化效率,可以提高网络吞吐量

fs.createReadStream()的工作方式是在内存中准备一段Buffer,然后fs.read()读取时逐步从磁盘中将字节复制到Buffer中。完成一次读取,则从这个Buffer中通过slice方法取出部分数据作为一个小Buffer对象,再通过data事件传递给调用方,如果Buffer用完则重新分配一个;如果还有剩余则继续使用

 类似资料: