buffer 是一个元素为16进制的两位数的类数组对象
Buffer是一个典型的JavaScript与C++结合的模块,它将性能相关部分用C++实现,将非性能
相关的部分用JavaScript实现
Buffer内存分配
Buffer对象的内存分配不是在V8的堆内存中,而是在Node的C++层面实现内存的申请的
Node在内存的使用上应用的是在C++层面申请内存、在JavaScript中分配内存的策略
Node以8 KB为界限
来区分Buffer是大对象还是小对象
Buffer 所采用的内存分配机制是slab
slab
是一种动态内存管理机制 通过预先申请事后分配的方式运转
slab就是一块申请好固定大小的内存区域,它有三个状态 full
完全分配partial
部分分配 empty
没有被分配
buffer 的转换
Buffer对象可以与字符串之间相互转换
。目前支持的字符串编码类型有如下这几种。
- ASCII
- UTF-8
- UTF-16LE/UCS-2
- Base64
- Binary
- Hex
字符串转Buffer对象主要是通过构造函数完成的
new Buffer(str, [encoding])
Buffer提供了一个isEncoding()函数来判断编码是否支持转换
Buffer.isEncoding(encoding)
对于不支持的编码类型,可以借助Node生态圈中的模块完成转换。iconv和iconv-lite
两个
模块可以支持更多的编码类型转换
iconv-lite采用纯JavaScript实现,iconv则通过C++调用libiconv库完成
。前者比后者更轻量,
无须编译和处理环境依赖直接使用。在性能方面,由于转码都是耗用CPU,在V8的高性能下,少
了C++到JavaScript的层次转换,纯JavaScript的性能比C++实现得更好
iconv-lite无法转换的内容如果是多字节,会输出? ;如果是单字节,则输出?。iconv则有三级降级策略,会尝试翻译无法转换的内容,或者忽略这些内容。如果不设置忽略,iconv对于无法转换的内容将会得到EILSEQ异常
了可读流还有一个设置编码的方法setEncoding()
readable.setEncoding(encoding)
该方法的作用是让data事件中传递的不再是一个Buffer对象,而是编码后的字符串
正确的拼接方式是用一个数组来存储接收到的所有Buffer片段并记录下所有片段的总长度, 然后调用Buffer.concat()方法生成一个合并的Buffer对象。
var chunks = [];
var size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
var buf = Buffer.concat(chunks, size);
var str = iconv.decode(buf, 'utf8');
console.log(str);
});
Buffer 与性能
通过预先转换静态内容为Buffer对象,可以有效地减少CPU的重复使用,节省服务器资源。 在Node构建的Web应用中,可以选择将页面中的动态内容和静态内容分离,静态内容部分可以通 过预先转换为Buffer的方式,使性能得到提升。由于文件自身是二进制数据,所以在不需要改变 内容的场景下,尽量只读取Buffer,然后直接传输,不做额外的转换,避免损耗