美文网首页
《深入浅出Node.js》Buffer

《深入浅出Node.js》Buffer

作者: 我叫Aliya但是被占用了 | 来源:发表于2022-04-15 11:22 被阅读0次

Buffer 是一个典型的 JavaScript 与 C++结合的模块,其性能相关部分用 C++实现,非性能相关的用 js 实现。

Buffer 所占用的内存不是通过 V8 分配的,属于 V8 堆外内存。真正的内存是在 C++层面提供的,JavaScript 层面只是使用它:

  • 小而频繁的 Buffer 操作,采用 slab 的机制(内存由 C++先申请、js 后分配,避免过多内存申请方面的系统调用)
  • 大块的 Buffer 操作,直接使用 C++层面提供的内存,而无需细腻的分配操作

常用函数

new Buffer()已被弃用

  • Buffer.from 字符串转 Buffer

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

  • Buffer.isEncoding('GBK') === false 支持的编码类型有限

  • Buffer.alloc(size, [fill = 0, encoding = 'utf8']) 创建指定大小 Buffer

    • 给元素的赋值(合法值为 0 到 255 之间的整数):
      • < 0,逐次+256 直至正常
      • 255,逐次-256
        - 小数,舍弃小数部分

  • buf.write(string,[offset = 0, length = string.length, encoding = 'utf8']) 向 Buffer 中写入数据:根据 encoding 将 string 写入 buf 的 offset 处

  • Buffer.concat(bufArray, allBufSize) 拼接 Buffer

拼接 Buffer

当两个 Buffer 相加时实际上buf1 + buf2 === buf1.toString() + buf2.toString()。所以在操作流时的 data、end 事件回调,要小心操作数据,以免出现半个字符的情况导致乱码

给流指定编码可以修正此问题stream.setEncoding("utf8"),但此方法仅支持 UTF-8、Base64 和 UCS-2/UTF-16LE 这 3 种编码。

Buffer.concat方法需要把所有 buffer 先存放在一个临时变量,待拼接后再处理(V8 堆外内存,不够用的话就是另一个问题了)。

处理更多编码类型

iconv-lite 采用纯 JavaScript 实现,iconv 则通过 C++调用 libiconv 库完成。在性能方面,由于转码都是耗用 CPU,在 V8 的高性能下,少了 C++到 JavaScript 的层次转换,纯 JavaScript 的性能比 C++实现得更好。

iconv-lite 无法转换的内容如果是多字节,会输出 �;如果是单字节,则输出?

iconv 则有三级降级策略,可能设置为尝试翻译、忽略

var iconv = new Iconv("UTF-8", "ASCII//TRANSLIT//IGNORE");
iconv.convert("ça va が"); // "ca va "

性能

网络传输字符串时,会先将字符串转换为 Buffer 后再传输,所以静态内容预先转换为 Buffer 对象,可以减少 CPU 的重复使用,节省服务器资源。

文件操作时,highWaterMark 太大会浪费内存,过小可能导致系统调用次数过多。highWaterMark 越大读取速度越快。

相关文章

网友评论

      本文标题:《深入浅出Node.js》Buffer

      本文链接:https://www.haomeiwen.com/subject/sjwfertx.html