ArrayBuffer

70 阅读3分钟

ArrayBuffer与TypedArray、DataView的设计

ArrayBuffer是在内存中开辟一块空间,存储数据,但是数据是什么,它不关注。 TypedArray、DataView是定义数据的类型,方便使用数据。

为什么这么设计?

  1. 职责分离
  2. 安全性
  3. 性能
  4. 灵活

- 职责分离

如果ArrayBuffer中需要关注什么内容数据,就需要关注数据存储的位数、设备是大端字序还是小端字序等因素。在数据传输时需要有区分。

- 安全性

由TypedArray、DataView校验位数、转换规范化,保障了内存访问的安全

- 性能

TypedArray同一种数据类型,提高了性能

- 灵活性

DataView存储多种数据,解决字节序转换过程,增加了js与其他应用系统的对接能力

ArrayBuffer

ArrayBuffer中的数据与js中的数据是否有编码转换? 存在的。基本转换规则如下:

- 从 ArrayBuffer 到js程序:定位字节-读取原始字节-解释和转换(确定整数/浮点数-处理字节序-转换为 JavaScript 格式) 

⁃ 从js程序到 ArrayBuffer:类型检查和范围截断 - 转换和规范化(截断/环绕/字节序) - 写入原始字节

Uint8C: 与其他整数转换有些差异

  • 在数据存储过程,对数据的转换规范化环节的截拦、环绕不一样的处理,Uint8采用了四舍五入、饱和的方式(其他采用拦截、环绕)。
  • 比较适合使用在图片处理上

BigUint64 -基于BigInt,牺牲了性能,确保了处理 64 位整数时的绝对精度 -性能比较低,需要特殊处理

Float -数据转换成IEE 754标准,存入buffer中

Float64Array是否存在转换 -不是直接内存拷贝,在引擎内部的表示形式,JavaScript 引擎的内部优化,数字的存储格式并不总是标准的 64 位格式,因此写入 Float64Array 时需要一个“确保格式规范”的步骤 -没有值转换 -性能依然极高 -从数值意义上讲,没有转换;但从底层的内存表示上讲,通常需要一次“规范化”以确保格式正确

SharedArrayBuffer

ArrayBuffer不能被多个线程同时使用,SharedArrayBuffer提供了该能力。

ShareArrayBuffer在worker中传输是如何实现的

  • 在主线程中创建Transferable Objects
  • 传递引用
  • 在Worker 线程中接收。event.data 就是一个的 SharedArrayBuffer 对象。这个新的 SharedArrayBuffer 对象指向的是操作系统中的同一块物理内存
  • 实现共享

ShareArrayBuffer安全考量: 需要使用ShareArrayBuffer的web页面增加安全机制:

  • Cross-Origin-Opener-Policy: same-origin
  • Cross-Origin-Embedder-Policy: require-corp

SharedArrayBuffer 与ArrayBuffer 的transfer特性区别

  • transfer是转移,转移后就不能再再操作了,除非再转回来;如果多个线程就回需要知道该转给谁;SharedArrayBuffer不需要,只要保证数据安全即可。
  • 20M的数据,使用json大约70ms,SharedArrayBuffer 在1ms以内

TypedArray&DataView

TypedArray:

  • 使用系统默认的字节序
  • 数据是相同类型

如何判断系统默认采用哪一种字节序? 建立2个字节的buffer,第一个存放1,第二个存放0,再使用16进制取数据是否等于256.

DataView

  • 可以灵活设置不同的字节序
  • 可以使用不同的数据类型存储读写

Atomics

Atomics是用来解决sharedArrayBuffer的资源竞争问题。

  • 现代 JavaScript 引擎通常使用 Futex(Fast Userspace Mutex)来实现 wait() 和 notify()。
  • 在主线中创建lock的sharedArrayBuffer,利用系统例如Futex机制,通知锁的变化。

兼容性

ios/安卓

  • ArrayBuffer:支持,4.2/4(其中transfer 17.4/114)
  • TypedArray:支持,4.2/4
  • ShareArrayBuffer/Atomics:15.2/68

api详情