JavaScript最初是为浏览器设计的,没有读取或操作二进制数据流的机制。Buffer类的引入让NodeJS具备了操作文件流或者网络二进制流的能力。Buffer的基本概念Buffer对象的内存分配并不在V8的堆内存中,而是Node在C++层面进行内存申请。可以理解为在内存中单独开辟了一部分空间,但是使用过程中内存的分配是由Node层面完成的,释放也是由Node.js中v8的gc机制自动控制的。Buffer的基本操作这里不再赘述,官方文档很详细。Buffer性能对比通常,数据在网络传输过程中需要转换到Buffer中。我们来做一个性能对比实验。1.使用纯字符串返回给客户端consthttp=require('http');lethello=''for(vari=0;i<10240;i++){hello+="a";}console.log(`Hello:${hello.length}`)//hello=Buffer.from(hello);http.createServer((req,res)=>{res.writeHead(200);res.end(hello);}).listen(8001);使用ab-c200-t100http://127.0.0.1:8001/命令进行性能测试,发起200个并发客户端使用字符串,QPS可以达到4019.70,传输速率为40491.45KB/秒。2.使用缓冲区。将字符串转换为Buffer对象并将其发送给客户端。consthttp=require('http');lethello=''for(vari=0;i<10240;i++){hello+="a";}console.log(`Hello:${hello.length}`)hello=Buffer.from(hello);http.createServer((req,res)=>{res.writeHead(200);res.end(hello);}).listen(8001);取消Bufferconversion的注释,同样使用ab-c200-t100http://127.0.0.1:8001/测试,同时发起200个并发客户端。使用Buffer,QPS达到7130.05,传输速率71822.74KB/秒。性能是原来的177%,大大节省了服务器资源。上面的对比例子参考《深入浅出Node JS》。那么问题来了,为什么会有这么大的性能提升呢?原因其实很简单。在NodeJS中,在进行http传输时,如果返回的类型是string,会将string类型的参数转换成Buffer,通过NodeJS中的Stream一点一滴的返回给客户端。如果我们直接返回Buffer类型,没有转换操作,直接返回降低了CPU复用率。这部分逻辑见Node源码https://github.com/nodejs/node/blob/v10.9.0/lib/_http_outgoing.js#L612在上面的性能对比例子中,当返回一个字符串时,每次请求需要加载的字符串用Buffer替换并返回;直接返回Buffer的时候,这个Buffer是在我们启动服务的时候保存在内存中的,每次请求都可以直接返回内存中的Buffer,所以使用Buffer前后的QPS提升了很多。因此,我们在编写业务代码时,可以将一些资源预先转换为Buffer类型(如js、css等静态资源文件),直接将buffer返回给客户端。比如在一些文件转发场景中,将获取到的内容存储为Buffer,直接转发,避免了额外的转换操作。参考资料:http://nodejs.cn/api/buffer.htmlhttps://book.douban.com/subje...
