<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ? ? ? 我在Chrome的[最新動態](http://blog.csdn.net/hfahe/article/details/7408426)里提到了Typed Arrays(Typed Array,類型數組)這個概念,可能對很多人來說非常陌生,那么它是什么,又有什么用途呢? **之前的問題** ? ? ??Web應用程序變得越來越強大,例如新增了音視頻處理、WebSocket等多個功能特性。毫無疑問,如果Javascript能夠快速方便的操作原始二進制數據會相當的有用。過去,我們必須要把原始數據當作字符串來處理,并且使用charCodeAt方法來從數據緩沖區中讀取字節。 ? ? ??但是這種方法需要多次轉換數據(尤其在二進制數據不是字節格式的數據時,例如32位整數或者浮點數),所以非常慢而且容易出錯。 ? ? ??Javascript需要一種機制來更有效的訪問原始的二進制數據,由此產生了類型數組。 **定義** ? ? ??其實除了Javascript,類型數組在其他很多語言中也有。它是一種數組,只有一種變量的類型。例如,一個float類型的數組將只包含浮點數而不能混用字符串和浮點數。此外,一個類型數組在初始化后不能改變大小。它看起來形式和普通Javascript數組很像,但是數據格式是一致和同一類型的(例如聲音或者像素點的緩沖數據)。 ? ? ??類型數組的規范參見[這里](http://www.khronos.org/registry/typedarray/specs/latest/)。這個規范實質上定義了一種arrayBuffer類型,相當于一個普通的定長二進制緩沖區。我們不能直接訪問和操作arrayBuffer的內容,而需要類型數組來創建arrayBuffer的視圖(從技術上來說,類型數組等同于arrayBuffer,因為它們本質上是一樣的)。例如,要訪問32位有符號整數數組作為緩沖區,會創建一個Int32Array的類型數組來指向arrayBuffer。 ? ? ??多個類型數組視圖可以指向同一個arrayBuffer,采用不同的類型、不同的長度以及不同的位移。例如下面的代碼: ~~~ // 創建一個8字節的ArrayBuffer var b = new ArrayBuffer(8); // 創建一個指向b的視圖v1,采用Int32類型,開始于默認的字節索引0,直到緩沖區的末尾 var v1 = new Int32Array(b); // 創建一個指向b的視圖v2,采用Uint8類型,開始于字節索引2,直到緩沖區的末尾 var v2 = new Uint8Array(b, 2); // 創建一個指向b的視圖v3,采用Int16類型,開始于字節索引2,長度為2 var v3 = new Int16Array(b, 2, 2); ~~~ ? ? ??上述代碼里變量的數據結構如下所示。 ![](https://box.kancloud.cn/2016-08-09_57a9a2e357378.jpg) 變量的數據結構 ? ? ??類型數組包括以下幾種類型: <table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top" style="background:#4F81BD;"><p align="left"><strong>名稱</strong></p></td> <td valign="top" style="background:#4F81BD;"><p align="left"><strong>大小 (以字節為單位)</strong></p></td> <td valign="top" style="background:#4F81BD;"><p align="left"><strong>說明</strong></p></td> </tr><tr><td valign="top"><p align="left"><strong>Int8Array</strong></p></td> <td valign="top"><p align="left">1</p></td> <td valign="top"><p align="left">8位有符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Uint8Array</strong></p></td> <td valign="top"><p align="left">1</p></td> <td valign="top"><p align="left">8位無符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Int16Array</strong></p></td> <td valign="top"><p align="left">2</p></td> <td valign="top"><p align="left">16位有符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Uint16Array</strong></p></td> <td valign="top"><p align="left">2</p></td> <td valign="top"><p align="left">16位無符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Int32Array</strong></p></td> <td valign="top"><p align="left">4</p></td> <td valign="top"><p align="left">32位有符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Uint32Array</strong></p></td> <td valign="top"><p align="left">4</p></td> <td valign="top"><p align="left">32位無符號整數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Float32Array</strong></p></td> <td valign="top"><p align="left">4</p></td> <td valign="top"><p align="left">32位浮點數</p></td> </tr><tr><td valign="top"><p align="left"><strong>Float64Array</strong></p></td> <td valign="top"><p align="left">8</p></td> <td valign="top"><p align="left">64位浮點數</p></td> </tr></tbody></table> ? ? ??類型數組實際上目前是作為WebGL的一部分來實現的(和它相關的還有File API),但是它可以用在任何地方。 ? ? ??下面我們來談談類型數組的優點和用途。 **優點** 1、? 性能優秀 ? ? ??所有類型數組相關的文檔都提到的重要一點是,類型數組比傳統數組快的多,具有非常好的性能。因為類型數組實際上是作為一個固定的內存塊來進行訪問的,而傳統的普通Javascript數組使用的是Hash查找方式(因為元素長度不定)。 ? ? ??這里有一個簡單的測試結果,在Firefox4 Beta1版本,我們對比了一個普通數組和Float32Array數組在操作1億個元素時每種操作所花費的時間。這個測試運行在Win7 64位、4G內存和Intel雙核1.3G CPU的平臺上。我們運行這個測試8次并使用其中最慢的一個時間。需要指出的是,普通Javascript數組的寫入操作經常花費超過10秒鐘,這會導致出現運行緩慢的腳本對話框。 <table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top" style="background:#4F81BD;"><p><strong><span style="color:white;">操作</span></strong></p></td> <td valign="top" style="background:#4F81BD;"><p><strong><span style="color:white;">普通數組</span></strong></p></td> <td valign="top" style="background:#4F81BD;"><p><strong><span style="color:white;">Float32Array</span></strong></p></td> </tr><tr><td valign="top"><p><strong>寫</strong></p></td> <td valign="top"><p>8947</p></td> <td valign="top"><p>1455</p></td> </tr><tr><td valign="top"><p><strong>讀</strong></p></td> <td valign="top"><p>1948</p></td> <td valign="top"><p>1109</p></td> </tr><tr><td valign="top"><p><strong>循環復制</strong></p></td> <td valign="top"><p>&gt;10,000</p></td> <td valign="top"><p>1969</p></td> </tr><tr><td valign="top"><p><strong>片段復制</strong></p></td> <td valign="top"><p>1125</p></td> <td valign="top"><p>503</p></td> </tr></tbody></table> ? ? ??下面我們有一個關于普通數組、類型數組(arrayBuffer)以及imageData之間性能的比較,可以看到arrayBuffer會快得多。 ![](https://box.kancloud.cn/2016-08-09_57a9a2e369afd.jpg) 性能優異的arrayBuffer ? ? ??其實在類型數組之前,Javascript也支持二進制字節的數組,這就是imageData。imageData是Canvas元素2D上下文環境里定義的數據類型。當在Canvas 2D里調用getImageData或者createImageData方法時就創建了imageData。imageData的data屬性是一個字節數組,它實際大小是圖片寬*高的四倍(因為每個像素有R、G、B、A四個通道)。之前我們在《[用HTML5創建超酷圖像灰度漸變效果](http://blog.csdn.net/hfahe/article/details/6208765)》這篇文章里就用到了imageData。 ? ? ??從圖表數據來看,imageData和arrayBuffer在多個瀏覽器里創建的性能遠遠高于普通的數組([數據來源](http://blog.n01se.net/?p=248))。不過這里有一個問題,后面將會提到。 ? ? ??可以想見,因為優秀的性能表現,類型數組可以廣泛的應用于Javascript圖像以及視頻的處理和壓縮,還有一些需要復雜運算的場景例如MD5計算中,讓功能可以更快速更高效的完成。例如我們先把imageData轉換為類型數組以換取更快的執行速度,如下面的代碼: ~~~ var canvas = document.getElementById('canvas'); var canvasWidth = canvas.width; var canvasHeight = canvas.height; var ctx = canvas.getContext('2d'); var imageData = ctx.getImageData(0,0, canvasWidth, canvasHeight); var buf =new ArrayBuffer(imageData.data.length); var data =new Uint32Array(buf); for(var y =0; y < canvasHeight;++y){ for(var x =0; x < canvasWidth;++x){ var value = x * y &0xff; data[y * canvasWidth + x]= (255 <<24)| // alpha (value <<16)| // blue (value << 8)| // green value; // red } } ~~~ ? ? ??另外一方面,因為類型數組可以顯著增加HTML5 Canvas 2D Web App的性能,所以這一特性對于使用HTML5來創建Web游戲的開發者會非常重要。 ? ? ??下面是兩個使用類型數組的示例。 ? ? ??第一個是Energy2D的[演示](http://visual-demos.dev.concord.org/seasons/earth/model2d.html),用于對比普通數組和類型數組的性能,大家可以自行體驗。 ![](https://box.kancloud.cn/2016-08-09_57a9a2e37f51f.jpg) Energy2D演示 ? ? ??第二個示例是使用類型數組、FileAPI以及Web Workers實現的SHA1[在線計算器](http://antimatter15.github.com/js-typed-array-sha1/),它的性能相當出色。正是在類型數組的支持下,Javascript執行SHA1、MD5這樣復雜運算的速度變得越來越快。 ![](https://box.kancloud.cn/2016-08-09_57a9a2e392e7d.jpg) 類型數組支持的在線SHA1計算器 2、? 二進制支持 ? ? ??上文曾經提到類型數組最主要的特點是支持二進制數據。的確,現在HTMl5的許多API涉及音視頻和實時通信,這些功能經常依賴于二進制文件格式,例如MP3音頻、MP4視頻和PNG圖像。二進制格式對于減少帶寬,提高性能,以及與現有文件格式互相轉換來說非常重要。 ? ? ??類型數組使得Web應用可以使用多種二進制文件格式和直接操作文件的二進制內容,例如從現有的媒體文件中提取數據。 ? ? ??在IE10上,已經提供了類型數組的支持(支持WebGL其實是微軟非常糾結的事情)。我們可以看看微軟所提供的二進制文件檢測器的[例子](http://ie.microsoft.com/testdrive/HTML5/TypedArrays/): ![](https://box.kancloud.cn/2016-08-09_57a9a2e3a8074.jpg) ? ? ??在這個示例里,我們可以獲取音樂文件的ID3頭,視頻文件的原始字節數據,以及附加文件的格式。它的核心代碼如下: ~~~ function getHexChunk(buffer, startAt) { var chunkLength = Math.min(CHUNK_SIZE, buffer.byteLength - startAt) var uints = new Uint8Array(buffer, startAt, chunkLength); var rowString = ""; for (var row = 0; row < uints.length; row += 16) { var remaining = uints.length - row; rowString += intToHexString(row + startAt, 8); rowString += " "; for (var offset = 0; offset < 8 ; offset++) { if (offset < remaining) rowString += intToHexString(uints[row + offset], 2) + " "; else rowString += " "; } rowString += " "; for (; offset < 16; offset++) { if (offset < remaining) rowString += intToHexString(uints[row + offset], 2) + " "; else rowString += " "; } rowString += " "; for (var offset = 0; offset < 8; offset++) { rowString += charForInt(uints[row + offset]); } for (; offset < 16; offset++) { rowString += charForInt(uints[row + offset]); } rowString += "\n"; } return rowString; } ~~~ ? ? ??頁面上文件的二進制格式輸出就是用這段代碼實現的。 **具體應用** [? ? ? ??這里](http://blog.digitalbackcountry.com/2012/01/dealing-with-binary-data-from-a-canvas-object-using-javascript-typedarrays/)有一個使用類型數組在Canvas圖像和二進制數據之間互相轉換,然后通過WebSocket發送的示例。作者提到“在我實現二進制WebSocket示例時,我學習了很多Javascript類型數組的知識,了解了如何把對象轉換為二進制數據。我寫了一個示例來獲取Canvas圖像數據,并且把它通過二進制的WebSocket連接發送出去。WebSocket服務器獲取圖像數據,然后把它發送給所有連接的客戶端(宇捷:這讓我想起了最近國外非常火爆的超人氣應用[DrawSomething-你畫我猜](http://game.163.com/12/0322/17/7T7G2FL200314OSE.html),我們可以用這種方式實現類似的WebApp),然后客戶端再把Canvas數據還原為PNG圖片。采用這種方式發送圖像數據比起base64編碼來更有效率(數據小33%,而且更利于序列化和存儲)。” ![](https://box.kancloud.cn/2016-08-09_57a9a2e3c40a5.jpg) 創造了歷史的應用-你畫我猜 ? ? ??WebSocket支持二進制數據傳輸,對于WebSocket服務器來說,使用二進制數據會比UTF-8更為簡單,不過現在瀏覽器支持方面還有問題。 ? ? ??示例里實現將Canvas數據轉換為二進制格式的代碼如下: ~~~ imagedata = context.getImageData(0, 0, imagewidth,imageheight); var canvaspixelarray = imagedata.data; var canvaspixellen = canvaspixelarray.length; var bytearray = new Uint8Array(canvaspixellen); for (var i=0;i<canvaspixellen;++i) { bytearray[i] = canvaspixelarray[i]; } ~~~ ? ? ??而把二進制數據還原為圖像的代碼如下,請注意我們不能直接從arrayBuffer獲取數據直接放到Canvas中。 ~~~ var bytearray =new Uint8Array(event.data); var tempcanvas = document.createElement('canvas'); tempcanvas.height= imageheight; tempcanvas.width= imagewidth; var tempcontext = tempcanvas.getContext('2d'); var imgdata = tempcontext.getImageData(0,0,imagewidth,imageheight); var imgdatalen = imgdata.data.length; for(var i=8;i<imgdatalen;i++) { imgdata.data[i]= bytearray[i]; } tempcontext.putImageData(imgdata,0,0); ~~~ ? ? ??在Adobe的官網上,也有一個類似的[完整示例](http://www.adobe.com/devnet/html5/articles/real-time-data-exchange-in-html5-with-websockets.html):《Real Time Data Exchange in HTML5 with WebSocket》。可以看到里面利用類型數組發送圖片的代碼如下: ~~~ function sendphoto() { imagedata = context.getImageData(0, 0, imagewidth,imageheight); var canvaspixelarray = imagedata.data; var canvaspixellen = canvaspixelarray.length; var bytearray = new Uint8Array(canvaspixellen); for (var i=0;i<canvaspixellen;++i) { bytearray[i] = canvaspixelarray[i]; } connection.send(bytearray.buffer); context.fillStyle = '#ffffff'; context.fillRect(0, 0, imagewidth,imageheight); } ~~~ **疑問** ? ? ??理論上來看,類型數組的性能毫無疑問比普通數組更快,但是根據《[現代瀏覽器里類型數組的性能](http://blog.n01se.net/?p=248)》一文中的評測,可以看到某些操作和某些瀏覽器下,類型數組的性能反而更低,另外imageData和ArrayBuffer的性能在同一瀏覽器中還有不同的表現。這個現象讓人困惑,因為imageData和ArrayBuffer其實就是為了性能敏感的功能誕生的,理論上能夠提供更快的讀取和寫入速度。這有極大可能是目前瀏覽器廠商對于二進制數組優化不足造成的。我希望瀏覽器未來對于類型數組能有更好的支持。 ![](https://box.kancloud.cn/2016-08-09_57a9a2e3db1fa.jpg) 某些操作和瀏覽器下,類型數組性能反而更低 **總結** ? ? ??隨著HTML5 Canvas、WebSocket等新特性的出現,WebApp能做的事情越來越多,同時Web App對于性能要求也越來越高,Javascript類型數組正是在這種情況下應運而生的。隨著IE、Chrome、Opera等主流瀏覽器逐步提供對它的全面支持,以及可預期的性能優化,它將會發揮越來越重要的作用。 **附:[類型數組的瀏覽器支持情況](http://caniuse.com/#feat=typedarrays)** 轉載請注明:來自[蔣宇捷的博客](http://blog.csdn.net/hfahe)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看