WdBly Blog

懂事、有趣、保持理智

周维的个人Blog

懂事、有趣、保持理智

站点概览

周维 | Jim

603927378@qq.com

推荐阅读

Node中Buffer的深度解析

Node中Buffer的深度解析

在Node中,应用需要处理网络协议、操作数据库、处理图片、接收上传文件等,在网络流和文件的操作中,还要处理大量二进制数据,JavaScript自有的字符串远远不能满足这些需求,于是Buffer对象应运而生。

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

系统级的Buffer

在操作系统中,也有一个Buffer,翻译为缓冲区,它的作用如下。

  • 用于临时存放IO设备上的数据,现代计算机遵循冯洛伊曼架构,CPU不能直接操作硬盘,需要通过内存间接操作,Buffer是用于缓存硬盘读写的数据。

  • 减少写入次数,下载大文件时,会先将文件下载到缓冲区,最后一次写入硬盘。

  • 应用程序无需等待真正写入到硬盘即可继续执行。

Node中的Buffer

简介

  • Buffer是典型的内建模块+核心模块结合的模块。

  • Node启动时就加载了Buffer模块,可以无需require即可使用

  • Buffer的元素为16进制的2位数,即0-255

作用

  • 处理大量二进制数据

  • 解决由于V8内存限制导致的无法读取超过2G的大文件。

  • 对比String有更优的性能

  • 字符串与Buffer之间有实质上的差异,即Buffer是二进制数据,字符串与Buffer之间存在编码关系

内存分配

Node采用了slab分配机制为Buffe分配内存

  • Node安装slab单元分配内存,每个slab单元为8kb。

  • 当首次分配一个小于8kb的Buffer时,从新的slab分配

image.png

  • 当再次分配时,优先检查已使用slab中是否有剩余空间,然后分配。

  • 只有当slab中所有Buffer都释放时,此slab才可以被回收。

  • 当Buffer大于8kb时,直接使用C++层提供的SlowBuffer分配。

  • 的内存是在Node的C++层面提供的

Buffer转换

  • 字符串转Buffer: new Buffer(str, [encoding]);

  • Buffer转字符串: buf.toString([encoding], [start], [end])

  • 判断Node中支持的编码类型: Buffer.isEncoding(encoding);

  • Buffer拼接:推荐使用第二种, 第一种的问题在于setEncoding支持的编码不多。

// 1、使用setEncoding var rs = fs.createReadStream('test.md', { highWaterMark: 11}); rs.setEncoding('utf8'); var data = ""; rs.on("data", function (chunk){ data += chunk; }); rs.on("end", function () { console.log(data); }); // 2、使用Buffer.concat 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代替字符串,可以提升传输效率和速率,增大网络吞吐量。

  • 对静态文件预先转换问Buffer,然后进行网络传输。(不要动态转换,因为转换过程需要消耗CPU资源)

  • fs.createReadStream()方法可以将文件已Buffer格式分段读取。highWaterMark属性设置大大影响此方法的性能。

参考资源:
《深入浅出Node.js》

提交

全部评论0

暂时没有评论...