「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。
1. Buffer结构
Buffer是一个像Array的对象,但它主要用于操作字节。下面我们从模块结构和对象结构的层面上来认识它。
1.1 模块结构
Buffer是一个典型的JavaScript与C++结合的模块,它将性能相关部分用C++实现,将非性能相关的部分用JavaScript实现,如图所示。
Buffer所占用的内存不是通过V8分配的,属于堆外内存。
由于V8垃圾回收性的影响,将常用的操作对象用更高效和专有的内存分配回收策略来管理是个不错的思路。由于Buffer太过常见,Node在进程启动时就已经加载了它,并将其放在全局对象(global)上。
所以在使用Buffer时,无须通过require()即可直接使用。
1.2 Buffer对象
Buffer对象类似于数组,它的元素为16进制的两位数,即0到255的数值。
示例代码如下
var str ="深入浅出node.js";
var buf = new Buffer(str, 'utf-8'); console.log(buf);
// => <Buffer e6 b7 b1 e5 85 a5 e6 b5 85 e5 87 ba 6e 6f 64 65 2e 6a 73>
由上面的示例可见,不同编码的字符串占用的元素个数各不相同,上面代码中的中文字在 Buffer受Array类型的影响很大,可以访问length属性得到长度,也可以通过下标访问元素 在构造对象时也十分相似,代码如下:
var buf = new Buffer(100);
console.log(buf.length); // => 100
上述代码分配了一个长100字节的Buffer对象。
可以通过下标访问刚初始化的Buffer的元素代码如下:
console.log(buf[10]);
这里会得到一个比较奇怪的结果,它的元素值是一个0到255的随机值同样,我们也可以通过下标对它进行赋值:
buf[10] = 100;
console.log(buf[10]);// => 100
值得注意的是,如果给元素赋值不是0到255的整数而是小数时会怎样呢?
示例代码如下
buf[20]= -100;
console.log(buf[20]); // 156 buf[21]= 300;
console.log(buf[21]); // 44 buf[22] = 3.1415;
console,log(buf[22]);// 3
2. Buffer的应用场景
2.1 流
流是数据的集合(与数据、字符串类似),但是流的数据不能一次性获取到,数据也不会全部load到内存中,因此流非常适合大数据处理以及断断续续返回chunk的外部源。流的生产者与消费者之间的速度通常是不一致的,因此需要buffer来暂存一些数据。buffer大小通过highWaterMark参数指定,默认情况下是16Kb。
2.2 存储需要占用大量内存的数据
Buffer 对象占用的内存空间是不计算在 Node.js 进程内存空间限制上的。
3. Buffer释放
我们无法手动对buffer实例进行GC,只能依靠V8来进行,我们唯一能做的就是解除对buffer实例的引用