buffer node,buffer js
本文带你了解Node.js中的Buffer,看看缓冲区结构,缓冲区内存分配,缓冲区拼接等。希望对你有帮助!
node.js速度课程简介:进入学习
理解Buffer
JavaScript对字符串操作非常友好。
Buffer是一个类似Array的对象,主要用来操作字节。
Buffer结构
Buffer是JavaScript和C结合的典型模块,性能相关部分用C实现,非性能相关部分用JavaScript实现。
Buffer占用的内存不是V8分配的,而是属于堆外内存。由于V8垃圾收集性能的影响,使用更高效和专有的内存分配和收集策略来管理公共操作对象是一个好主意。
Buffer对象
buffer对象的元素不是十六进制两位数,即0-255的数值。
设buf 01=buffer . alloc(8);
console . log(buf 01);//Buffer 00 00 00 00 00 00 00 00 00可以使用fill来填充buf的值(默认为utf-8编码)。如果填充的值超过了buffer,则不会被写入。
如果要清空之前填充的内容,可以直接填充()
buf01.fill(12345678910 )
console . log(buf 01);//缓冲区31 32 33 34 35 36 37 38
console . log(buf 01 . tostring());//12345678如果填充的内容是中文,在utf-8的影响下,汉字会占据3个元素,字母和半角标点会占据1个元素。
设buf02=Buffer.alloc(18,开始我们的新旅程, utf-8 );
console . log(buf 02 . tostring());//首先,我们的新缓冲区受数组类型的影响很大。您可以访问length属性来获取长度,通过下标访问元素,或者通过indexOf检查元素位置。
console . log(buf 02);//缓冲区E5 BC 80 E5 a7 8b E6 88 91 E4 bb AC E7 9a 84 E6 96 B0
Console.log(buf02.length) //18字节
Console.log (BUF02 [6])//230:转换后E6为230
console . log(buf 02 . index of( I )//6:在第7个字节位置
Console.log (buf02.slice (6,9))。tostring())//I:Get buffer 6891,转换后为‘I’。如果对字节的赋值不是0255之间的整数,或者当赋值是十进制时,赋值小于0,则在值上逐个加上256,直到得到0255之间的整数。如果大于255,就一个个减去255。如果是小数,省略小数部分(不四舍五入)
Buffer内存分配
缓冲对象的内存分配不在V8的堆内存中,而是在Node的C级内存的应用。因为大量的字节数据是无法在需要一点内存的时候,通过向操作系统申请一点内存来处理的。为此Node采用了C级申请内存,JavaScript分配内存的方法。
节点采用slab分配机制,slab是一种介质动态内存管理机制,广泛应用于一些*nix操作系统,如Linux。
Slab是一个固定大小的应用内存区域。平板有以下三种状态:
Full:完全分配状态partial:部分分配状态empty:未分配状态节点以8KB为边界来区分缓冲区是大对象还是小对象。
console . log(buffer . poolsize);//8192
分配小buffer对象
如果指定的缓冲区大小小于8KB,Node会将其作为小对象进行分配。
构建一个新的板单元。目前slab处于空置状态。
构造一个1024KB的小缓冲对象,当前slab将被1024KB占用,记录slab是从哪里使用的。
然后创建另一个大小为3072KB的缓冲区对象。构造过程将判断当前板的剩余空间是否足够,如果足够,则使用剩余空间并更新板的分配状态。在使用了3072KB的空间后,该板中当前还剩4096KB。
如果此时创建一个6144KB的缓冲区,那么当前的slab空间不足,将会构造一个新的slab(这会浪费原slab的剩余空间)。
例如,在以下示例中:
Buffer.alloc(1)
Buffer.alloc(8192)第一个slab中只会有一个1字节的Buffer对象,后面的buffer对象会构建一个新的slab存储。
小结:
真正的内存是在Node的C层提供的,而JavaScript层只使用。在进行小而频繁的缓冲区操作时,采用slab机制进行预应用和时间分配,使得JavaScript和操作系统之间不需要过多的系统调用内存应用。对于大缓冲区,使用C级提供的内存即可,无需精细的分配操作。
Buffer的拼接
缓冲区在使用场景下通常是分段传输的。
const fs=require( fs );
Rs=fs.createreadstream(。/JingYeSi.txt ,{ flags: r });
设str=
rs.on(data ,(chunk)={
str=chunk
})
rs.on(end ,()={
console . log(str);
})以上是读流的例子,data time中获取的chunk对象是buffer对象。
但当输入流中存在宽字节编码(一个字占用多个字节)时,问题就暴露出来了。toString()操作隐藏在str=chunk中。相当于str=str . tostring()chunk . tostring()。
将以下可读流的每个读取缓冲区的长度限制为11。
Fs.createReadStream(。/JingYeSi.txt ,{flags: r ,high watermark:11 });输出:
上面有一段乱码,把缓冲区长度限制在11。对于任何长度的缓冲区,宽字节串都可能被截断,但缓冲区越长,出现的概率越低。
encoding
但是如果编码设置为utf-8,则不会出现此问题。
Fs.createReadStream(。/JingYeSi.txt ,{flags: r ,highwatermark: 11,编码: UTF-8 });
原因:尽管无论如何设置编码,流的触发时间都是相同的,但是当调用setEncoding时,在可读的流对象内部设置一个解码器对象。每个数据事件都通过decoder对象从缓冲区解码为字符串,然后传递给调用者。
string_decoder模块提供了一个API,用于将缓冲区对象解码为字符串(以保留编码的多字节UTF-8和UTF-16字符的方式)
const { string decode }=require( string _ decoder );
设s1=Buffer.from([0xe7,0xaa,0x97,0xe5,0x89,0x8d,0xe6,0x98,0x8e,0xe6,0x9c])
设s2=Buffer.from([0x88、0xe5、0x85、0x89、0xef、0xbc、0x8c、0x0d、0x0a、0xe7、0x96])
console . log(S1 . tostring());
console . log(S2 . tostring());
console . log(-);
const decoder=new string decoder( utf8 );
console . log(decoder . write(S1));
console.log(decoder.write(s2))。
Buffer与性能
缓冲区广泛应用于文件I/O和网络I/O,尤其是网络传输中,其性能起着重要的作用。在应用中,通常会对字符串进行操作,但一旦在网络中传输,就需要将其转换为缓冲区,用于二进制数据传输。在web应用程序中,字符串到缓冲区的转换一直在发生。提高字符串到缓冲区的转换效率可以大大提高网络吞吐量。
如果通过纯字符串发送给客户端,性能会比发送缓冲区对象差,因为缓冲区对象不需要每次响应都进行转换。通过预先将静态内容转换为缓冲对象,可以有效减少CPU重用,节省服务器资源。
可以选择将页面中的动态和静态内容分开,预先将静态内容转换成缓冲区,这样可以提高性能。
读取文件时,高水位线的设置对性能至关重要。在理想状态下,每次读取的长度是用户指定的高水位线。
高水位线的大小对性能有两个影响:
对缓冲内存的分配和使用有一定的影响。设置过小可能会导致过多的系统调用。更多关于node的信息,请访问:nodejs教程!以上是对Node.js中Buffer模块细节的简单了解更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。