web-dev-qa-db-ja.com

JavaScriptでArrayBufferと型付き配列を使用する場所

Node.jsからブラウザー環境に移行していますが、ArrayBufferと型付き配列(Uint8Arrayなど)についてはまだ混乱しています。

型付き配列を使用する場所、およびArrayBufferを直接使用する場所について混乱しています。一方を他方に、またはその逆に変換するのは難しくありませんが、どちらを使用するのですか?

たとえば、コード内のデータのチャンクを表すオブジェクトを作成する場合、ArrayBufferまたはUint8Arrayのどちらにする必要がありますか?何に依存していますか?

または:関数(たとえば、外部API)からArrayBufferを返すか、型付き配列を返す必要がありますか?

これらの型付き配列に要素などを正確に追加する方法をグーグルで検索できることに注意してください。私が不足しているのは、どこで何を使用するかについてのいくつかの短い一般的なガイドです。特に、ノードのバッファから移動する場合。

29
Karel Bílek

コンセプト

ArrayBuffer sは、物理メモリ内のバイト配列を表します。 ArrayBufferはバイトの実際のストレージですが、直接使用されることはほとんどありません。実際、ArrayBufferのコンテンツを直接読み取るためのアクセス権はなく、参照のみを渡すことができます。一方、サーバーとクライアント間のバイナリデータ転送、またはユーザーのファイルシステムからのブロブ経由の転送に使用されます。

ArrayBuffer byte array in memory
メモリ内のArrayBufferバイト配列-各インデックスは1バイトに相当します。 ArrayBufferはメモリ内で整列されます。

ArrayBufferのコンテンツを読み取るには、viewを使用する必要があります。これは一番上にあり、さまざまな幅のタイプまたは任意でバイトにアクセスするための「api」を提供します。

幅に依存するビュー

必要なものに応じて、異なるビューが使用されます。バイト値を読み取る必要がある場合、つまり-128〜127の符号付き値、または0〜255の符号なし値、Int8ArrayまたはUint8Arrayを使用します。それらの名前はビューであり、配列ではなく、基礎となるArrayBufferのみを参照するため、少し「誤解を招く」ことに注意してください。

同様に、 Int8Arrayint8Arrayint8ClampedArrayInt16Arrayint16Array のビューがあります、 Int32Arrayint3ArrayFloat32Array および Float64Array

* int8Arraysを除き、他のものにはArrayBufferサイズの要件があります。たとえば、Uint32Arrayビューは、4で割り切れるArrayBufferの上に配置する必要があります。そうしないと、エラーがスローされます。 * int 16ビューには2バイト境界が必要です。

ビューのコンストラクタを直接使用してインデックスの数を指定でき、これらの要件を満たすために一致するArrayBufferが自動的に作成されるため、これは通常は問題ではありません。

また、ArrayBufferはバイト配列であるため、* int16ビューはそこから2バイトを読み取ります-または、1つのインデックス= 2バイト、* int32 4、または1つのインデックス= 4バイトなど。

Uint8ArrayとUint8ClampedArrayの主な違いは、通常の配列では範囲外の値はモジュロ(たとえば256が0になる)の影響を受けることです。クランプされた配列では、値は代わりにクランプされた推奨値です(256は255になります)。

*int16 view
Int16/Uint16ビュー-各インデックスは2バイトを表し、メモリにアラインされています。

*int32 view
Int32/Uint32およびFloat32ビュー-各インデックスは4バイトを表し、メモリにアラインされています。

Float64 view
Float64ビュー-各インデックスは8バイトを表し、メモリにアラインされています。

柔軟性のためのDataView

次に、DataViewがあります。これは、柔軟なArrayBufferが必要であり、可変幅を読み取る必要があるシナリオや、必ずしも幅やメモリにアライメントされていないバッファーの位置からのシナリオを対象としています。

たとえば、* int32インデックスは常に4で割り切れるメモリ位置を指します。一方、DataViewは、たとえば位置5からUint32を読み取ることができ、内部的に必要なすべてのステップ(ビットシフト、マスキングなど)を処理しますが、わずかなオーバーヘッドがかかります。

もう1つの違いは、DataViewはインデックスではなく、それが表すデータの絶対バイト位置を使用し、任意の位置との間でさまざまな幅を読み書きする独自のメソッドが付属していることです。

DataView
DataView-任意の位置と幅から読み取ることができます。

他の場合は、同じ基盤のArrayBufferを参照する複数の異なるビューを使用できます。

現在、整数用の64ビットビューはありませんが、 ES8向けに提案 のようです。

SharedArrayBuffers

Webワーカー全体で使用できる新しい SharedArrayBuffers に言及することも役立ちます。

一部のブラウザでは過去に transferable objects を使用できました(そして引き続き使用できます)が、SharedArrayBuffersはメモリが同じままであるという意味でより効率的であり、それに関する情報のみが転送されます。 SharedBufferは、ArrayBuffersのようにデタッチできません。

目的と使用分野

型付き配列は、特定の数値を格納するのに適していて高速です。ビットマップは、型付き配列(canvas 2D/WebGLなど)の典型的な候補です。

Web Worker内のデータの大量のデータ処理も別の用途などです。クライアントとサーバーまたはファイルシステム間のバイナリ転送については既に説明しました。

DataViewsは、バイナリファイルとファイル形式の解析または構築に最適です。

型付き配列は、ネット経由でサーバーに送信したり、WebソケットやWebRTCのデータチャネルなどを介して送信したりするためのバイナリデータをパックする優れた方法です。

オーディオ、ビデオ、キャンバス、またはメディアの記録を扱う場合、多くの場合、型付き配列を使用する方法はありません。

型付き配列を使用するための鍵は、パフォーマンスとメモリです。それらは特別なシナリオで最もよく使用されますが、数値(またはutf-8文字列、暗号化ベクトルなど)のみを保存する必要がある通常の場合に使用しても問題はありません。これらは高速で、メモリフットプリントが低くなっています。

注意事項

知っておくべき注意事項がいくつかあります。

バイトオーダー

バイトオーダーに関しては、いくつかの予防措置が必要です。型付き配列は常に、実行されるCPUアーキテクチャを反映します。リトルエンディアンまたはビッグエンディアン。ほとんどのコンシューマシステムはリトルエンディアンですが、* int16および* int32配列を使用する場合は、バイト順に特に注意する必要があります。 DataViewもこの部分に役立ちますが、パフォーマンスが重要な場合、常に良い選択とは限りません。

サーバーからデータを受信する場合、バイトオーダーも重要です。通常、それらは常にビッグエンディアン形式(別名「ネットワーク順序」)です。ファイル形式の解析にも同じことが適用されます。

浮動小数点数エンコード

Float32/Float64は、 IEEE-754 形式でエンコードされた数値を読み書きします。これは、同じバッファに複数のビューが使用されている場合にも注意する必要があります。

クロスブラウザのサポート

ほとんどのブラウザは型付き配列をサポートしています 最近。古いブラウザーに対処する必要がある場合は、IE9または古いモバイルブラウザーに戻って使用できないようにする必要があります。

Safariはパフォーマンスに関して特に最適化されていませんが、他の利点もあります。バージョン5.1はFloat64をサポートしていません。

モバイルデバイスには独自のハードウェア制限がありますが、一般に、型付きアレイは安全に使用できます。特別な場合には polyfill があります。

59
user1693593