成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

怎么理解Node.js中的Buffer模塊

這篇文章主要講解了“怎么理解Node.js中的Buffer模塊”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“怎么理解Node.js中的Buffer模塊”吧!

10年積累的網(wǎng)站建設(shè)、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有楊浦免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

怎么理解Node.js中的Buffer模塊

理解Buffer

JavaScript對(duì)于字符串的操作十分友好

Buffer是一個(gè)像Array的對(duì)象,主要用于操作字節(jié)。

Buffer結(jié)構(gòu)

Buffer是一個(gè)典型的JavaScript和C++結(jié)合的模塊,將性能相關(guān)部分用C++實(shí)現(xiàn),將非性能相關(guān)部分用JavaScript實(shí)現(xiàn)。

怎么理解Node.js中的Buffer模塊

Buffer所占用的內(nèi)存不是通過(guò)V8分配,屬于堆外內(nèi)存。 由于V8垃圾回收性能影響,將常用的操作對(duì)象用更高效和專有的內(nèi)存分配回收政策來(lái)管理是個(gè)不錯(cuò)的思路。

Buffer在Node進(jìn)程啟動(dòng)時(shí)就已經(jīng)價(jià)值,并且放在全局對(duì)象(global)上。所以使用buffer無(wú)需require引入

Buffer對(duì)象

Buffer對(duì)象的元素未16進(jìn)制的兩位數(shù),即0-255的數(shù)值

let buf01 = Buffer.alloc(8);
console.log(buf01);  // <Buffer 00 00 00 00 00 00 00 00>

可以使用fill填充buf的值(默認(rèn)為utf-8編碼),如果填充的值超過(guò)buffer,將不會(huì)被寫入。

如果buffer長(zhǎng)度大于內(nèi)容,則會(huì)反復(fù)填充

如果想要清空之前填充的內(nèi)容,可以直接fill()

buf01.fill('12345678910')

console.log(buf01);   // <Buffer 31 32 33 34 35 36 37 38>
console.log(buf01.toString()); // 12345678

如果填入的內(nèi)容是中文,在utf-8的影響下,中文字會(huì)占用3個(gè)元素,字母和半角標(biāo)點(diǎn)符號(hào)占用1個(gè)元素。

let buf02 = Buffer.alloc(18, '開(kāi)始我們的新路程', 'utf-8');
console.log(buf02.toString());  // 開(kāi)始我們的新

BufferArray類型影響很大,可以訪問(wèn)length屬性得到長(zhǎng)度,也可以通過(guò)下標(biāo)訪問(wèn)元素,也可以通過(guò)indexOf查看元素位置。

console.log(buf02);  // <Buffer e5 bc 80 e5 a7 8b e6 88 91 e4 bb ac e7 9a 84 e6 96 b0>
console.log(buf02.length)  // 18字節(jié)
console.log(buf02[6])  // 230: e6 轉(zhuǎn)換后就是 230
console.log(buf02.indexOf('我'))  // 6:在第7個(gè)字節(jié)位置
console.log(buf02.slice(6, 9).toString())  // 我: 取得<Buffer e6 88 91>,轉(zhuǎn)換后就是'我'

如果給字節(jié)賦值不是0255之間的整數(shù),或者賦值時(shí)小數(shù)時(shí),賦值小于0,將該值逐次加256.直到得到0255之間的整數(shù)。如果大于255,就逐次減去255。 如果是小數(shù),舍去小數(shù)部分(不做四舍五入)

Buffer內(nèi)存分配

Buffer對(duì)象的內(nèi)存分配不是在V8的堆內(nèi)存中,而是在Node的C++層面實(shí)現(xiàn)內(nèi)存的申請(qǐng)。 因?yàn)樘幚泶罅康淖止?jié)數(shù)據(jù)不能采用需要一點(diǎn)內(nèi)存就向操作系統(tǒng)申請(qǐng)一點(diǎn)內(nèi)存的方式。為此Node在內(nèi)存上使用的是在C++層面申請(qǐng)內(nèi)存,在JavaScript中分配內(nèi)存的方式

Node采用了slab分配機(jī)制slab是以中動(dòng)態(tài)內(nèi)存管理機(jī)制,目前在一些*nix操作系統(tǒng)用中有廣泛的應(yīng)用,比如Linux

slab就是一塊申請(qǐng)好的固定大小的內(nèi)存區(qū)域,slab具有以下三種狀態(tài):

  • full:完全分配狀態(tài)

  • partial:部分分配狀態(tài)

  • empty:沒(méi)有被分配狀態(tài)

Node以8KB為界限來(lái)區(qū)分Buffer是大對(duì)象還是小對(duì)象

console.log(Buffer.poolSize);  // 8192

這個(gè)8KB的值就額是每個(gè)slab的大小值,在JavaScript層面,以它作為單位單元進(jìn)行內(nèi)存的分配

分配小buffer對(duì)象

如果指定Buffer大小小于8KB,Node會(huì)按照小對(duì)象方式進(jìn)行分配

  1. 構(gòu)造一個(gè)新的slab單元,目前slab處于empty空狀態(tài)

怎么理解Node.js中的Buffer模塊

  1. 構(gòu)造小buffer對(duì)象1024KB,當(dāng)前的slab會(huì)被占用1024KB,并且記錄下是從這個(gè)slab的哪個(gè)位置開(kāi)始使用的

怎么理解Node.js中的Buffer模塊

  1. 這時(shí)再創(chuàng)建一個(gè)buffer對(duì)象,大小為3072KB。 構(gòu)造過(guò)程會(huì)判斷當(dāng)前slab剩余空間是否足夠,如果足夠,使用剩余空間,并更新slab的分配狀態(tài)。 3072KB空間被使用后,目前此slab剩余空間4096KB。

怎么理解Node.js中的Buffer模塊

  1. 如果此時(shí)創(chuàng)建一個(gè)6144KB大小的buffer,當(dāng)前slab空間不足,會(huì)構(gòu)造新的slab(這會(huì)造成原slab剩余空間浪費(fèi))

怎么理解Node.js中的Buffer模塊

比如下面的例子中:

Buffer.alloc(1)
Buffer.alloc(8192)

第一個(gè)slab中只會(huì)存在1字節(jié)的buffer對(duì)象,而后一個(gè)buffer對(duì)象會(huì)構(gòu)建一個(gè)新的slab存放

由于一個(gè)slab可能分配給多個(gè)Buffer對(duì)象使用,只有這些小buffer對(duì)象在作用域釋放并都可以回收時(shí),slab的空間才會(huì)被回收。 盡管只創(chuàng)建1字節(jié)的buffer對(duì)象,但是如果不釋放,實(shí)際是8KB的內(nèi)存都沒(méi)有釋放

小結(jié):

真正的內(nèi)存是在Node的C++層面提供,JavaScript層面只是使用。當(dāng)進(jìn)行小而頻繁的Buffer操作時(shí),采用slab的機(jī)制進(jìn)行預(yù)先申請(qǐng)和時(shí)候分配,使得JavaScript到操作系統(tǒng)之間不必有過(guò)多的內(nèi)存申請(qǐng)方面的系統(tǒng)調(diào)用。 對(duì)于大塊的buffer,直接使用C++層面提供的內(nèi)存即可,無(wú)需細(xì)膩的分配操作。

Buffer的拼接

buffer在使用場(chǎng)景中,通常是以一段段的方式進(jìn)行傳輸。

const fs = require('fs');

let rs = fs.createReadStream('./靜夜思.txt', { flags:'r'});
let str = ''
rs.on('data', (chunk)=>{
    str += chunk;
})

rs.on('end', ()=>{
    console.log(str);
})

以上是讀取流的范例,data時(shí)間中獲取到的chunk對(duì)象就是buffer對(duì)象。

但是當(dāng)輸入流中有寬字節(jié)編碼(一個(gè)字占多個(gè)字節(jié))時(shí),問(wèn)題就會(huì)暴露。在str += chunk中隱藏了toString()操作。等價(jià)于str = str.toString() + chunk.toString()。

下面將可讀流的每次讀取buffer長(zhǎng)度限制為11.

fs.createReadStream('./靜夜思.txt', { flags:'r', highWaterMark: 11});

輸出得到:

怎么理解Node.js中的Buffer模塊

上面出現(xiàn)了亂碼,上面限制了buffer長(zhǎng)度為11,對(duì)于任意長(zhǎng)度的buffer而言,寬字節(jié)字符串都有可能存在被截?cái)嗟那闆r,只不過(guò)buffer越長(zhǎng)出現(xiàn)概率越低。

encoding

但是如果設(shè)置了encodingutf-8,就不會(huì)出現(xiàn)此問(wèn)題了。

fs.createReadStream('./靜夜思.txt', { flags:'r', highWaterMark: 11, encoding:'utf-8'});

怎么理解Node.js中的Buffer模塊

原因:雖然無(wú)論怎么設(shè)置編碼,流的觸發(fā)次數(shù)都是一樣,但是在調(diào)用setEncoding時(shí),可讀流對(duì)象在內(nèi)部設(shè)置了一個(gè)decoder對(duì)象。每次data事件都會(huì)通過(guò)decoder對(duì)象進(jìn)行buffer到字符串的解碼,然后傳遞給調(diào)用者。

string_decoder 模塊提供了用于將 Buffer 對(duì)象解碼為字符串(以保留編碼的多字節(jié) UTF-8 和 UTF-16 字符的方式)的 API

const { StringDecoder } = require('string_decoder');
let s1 = Buffer.from([0xe7, 0xaa, 0x97, 0xe5, 0x89, 0x8d, 0xe6, 0x98, 0x8e, 0xe6, 0x9c])
let 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 StringDecoder('utf8');
console.log(decoder.write(s1));
console.log(decoder.write(s2));

怎么理解Node.js中的Buffer模塊

StringDecoder在得到編碼之后,知道了寬字節(jié)字符串在utf-8編碼下是以3個(gè)字節(jié)的方式存儲(chǔ)的,所以第一次decoder.write只會(huì)輸出前9個(gè)字節(jié)轉(zhuǎn)碼的字符,后兩個(gè)字節(jié)會(huì)被保留在StringDecoder內(nèi)部。

Buffer與性能

buffer在文件I/O和網(wǎng)絡(luò)I/O中運(yùn)用廣泛,尤其在網(wǎng)絡(luò)傳輸中,性能舉足輕重。在應(yīng)用中,通常會(huì)操作字符串,但是一旦在網(wǎng)絡(luò)中傳輸,都需要轉(zhuǎn)換成buffer,以進(jìn)行二進(jìn)制數(shù)據(jù)傳輸。 在web應(yīng)用中,字符串轉(zhuǎn)換到buffer是時(shí)時(shí)刻刻發(fā)生的,提高字符串到buffer的轉(zhuǎn)換效率,可以很大程度地提高網(wǎng)絡(luò)吞吐率。

如果通過(guò)純字符串的方式向客戶端發(fā)送,性能會(huì)比發(fā)送buffer對(duì)象更差,因?yàn)閎uffer對(duì)象無(wú)須在每次響應(yīng)時(shí)進(jìn)行轉(zhuǎn)換。通過(guò)預(yù)先轉(zhuǎn)換靜態(tài)內(nèi)容為buffer對(duì)象,可以有效地減少CPU重復(fù)使用,節(jié)省服務(wù)器資源。

可以選擇將頁(yè)面中動(dòng)態(tài)和靜態(tài)內(nèi)容分離,靜態(tài)內(nèi)容部分預(yù)先轉(zhuǎn)換為buffer的方式,使得性能得到提升。

在文件的讀取時(shí),highWaterMark設(shè)置對(duì)性能影響至關(guān)重要。在理想狀態(tài)下,每次讀取的長(zhǎng)度就是用戶指定的highWaterMark。

highWaterMark大小對(duì)性能有兩個(gè)影響的點(diǎn):

  • 對(duì)buffer內(nèi)存的分配和使用有一定影響

  • 設(shè)置過(guò)小,可能導(dǎo)致系統(tǒng)調(diào)用次數(shù)過(guò)多

感謝各位的閱讀,以上就是“怎么理解Node.js中的Buffer模塊”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)怎么理解Node.js中的Buffer模塊這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

新聞名稱:怎么理解Node.js中的Buffer模塊
標(biāo)題鏈接:http://jinyejixie.com/article26/iehjcg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google網(wǎng)站設(shè)計(jì)、面包屑導(dǎo)航、商城網(wǎng)站虛擬主機(jī)、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司
南雄市| 如东县| 甘谷县| 威远县| 辽宁省| 永德县| 怀柔区| 本溪市| 本溪市| 彭阳县| 科尔| 黄陵县| 瑞丽市| 山阳县| 黑水县| 大渡口区| 科尔| 瑞丽市| 老河口市| 石首市| 闸北区| 河东区| 宁津县| 嘉义县| 扬州市| 西畴县| 玛多县| 芮城县| 美姑县| 麦盖提县| 新宁县| 武威市| 法库县| 南岸区| 张家川| 龙泉市| 黑河市| 蕲春县| 县级市| 华亭县| 三原县|