Javascript 在Blob和ArrayBuffers之间转换而不复制?
我在Javascript中的ArrayBuffers和Blob之间转换的文档中找不到任何性能信息。我认为标准方法是:Javascript 在Blob和ArrayBuffers之间转换而不复制?,javascript,performance,arraybuffer,Javascript,Performance,Arraybuffer,我在Javascript中的ArrayBuffers和Blob之间转换的文档中找不到任何性能信息。我认为标准方法是: const blob = new Blob([arrayBuffer]) 及 请注意,我只关心内存中的blob,而不是基于文件的blob(因此不涉及I/O时间)。我在codepen中进行了一些计时: 这表明这两个操作都会根据ArrayBuffer的大小在时间上进行缩放,因此它们很可能是在复制数据。 事实上,如果我的计时代码准确的话,仅仅创建一个新的响应(blob)对于一个更大的
const blob = new Blob([arrayBuffer])
及
请注意,我只关心内存中的blob,而不是基于文件的blob(因此不涉及I/O时间)。我在codepen中进行了一些计时:
这表明这两个操作都会根据ArrayBuffer的大小在时间上进行缩放,因此它们很可能是在复制数据。
事实上,如果我的计时代码准确的话,仅仅创建一个新的响应(blob)
对于一个更大的blob需要更长的时间。另外,新的Blob.arrayBuffer()
函数也似乎是O(n),尽管它比响应方式
快。但在2020年浏览器还没有很好的支持
所以我的问题是:是否有关于这些操作预期性能的权威文件?我只是用错了吗?有没有更快(固定时间、零拷贝)的方法?冒着回答老问题的风险,对后代来说——您要查找的权威文档将分别是
Blob
和ArrayBuffer
的[相关章节]和规范
就我所能确定的,两个规范都没有为任何一类对象指定特定的分配方案;虽然ECMAScript对ArrayBuffer
的规范似乎更能暗示特定的数据分配机制,但这只是在规范本身的范围内——我找不到类似“必须在堆上分配数据”这样的内容;而Blob
的规范在包含“Blob”的数据的实际分配位置和方式方面故意更加抽象和模糊
在这些规范的指导下,大多数用户代理都会在堆上天真地分配相应的ArrayBuffer
length的数据,而构造的blob对象可以由内存映射文件有效地支持(例如,在File
blob的情况下)这基本上会使它们在某些操作系统上得到页面文件的支持——这意味着在需要之前根本不会保留RAM(对于blob上的某些操作,比如将其转换为ArrayBuffer
)
因此,从Blob
到ArrayBuffer
的转换虽然在技术上没有指定为O(n)
,但在大多数用户代理中也是如此,因为后者有助于实际的即时读写数据访问(通过元素索引等),而Blob
本身不允许任何即时数据访问
现在,我说的是“大多数用户代理”,因为从技术上讲,您可以设计一个非常复杂的数据访问机制,具有写时复制语义,在从Blob
获取ArrayBuffer
时不分配数据(通过您在问题中描述的任何方法或更现代的API,例如)在需要读取和/或修改相应数据之前
换句话说,您的所有基准测试只涉及具体的实现(阅读您尝试过的用户代理),这些实现可以自由地实现任何一个类以及与之相关的操作,但是只要它们不违反相应的规范,它们看起来都是合适的
然而,如果有足够多的人开始采用前后激进的blob转换,那么没有任何东西可以阻止像Mozilla或Google这样的供应商将其实现优化为上面描述的(写时复制),例如,这可能会或可能不会使它们变成O(log(n))
操作。毕竟,JavaScript在很长一段时间内被称为“解释型”语言——但今天称之为解释型语言有点用词不当,因为Chrome的V8和Firefox的SpiderMonkey以优化的名义从中编译本机代码。而且,他们也可以自由地这样做——没有适用的语言规范或相关环境要求它“被解释”。Blob和数组缓冲区也是如此
不幸的是,在实践中,这意味着我们必须接受使用blob和数组缓冲区的程序的实际运行情况——通常,当您需要对blob做一些有用的事情时,这会产生真正的
O(n)
成本。冒着回答旧问题的风险,对于后代——您正在寻找的权威文档将分别是Blob
和ArrayBuffer
的[相关章节]和规范
就我所能确定的,两个规范都没有为任何一类对象指定特定的分配方案;虽然ECMAScript对ArrayBuffer
的规范似乎更能暗示特定的数据分配机制,但这只是在规范本身的范围内——我找不到类似“必须在堆上分配数据”这样的内容;而Blob
的规范在包含“Blob”的数据的实际分配位置和方式方面故意更加抽象和模糊
在这些规范的指导下,大多数用户代理都会在堆上天真地分配相应的ArrayBuffer
length的数据,而构造的blob对象可以由内存映射文件有效地支持(例如,在File
blob的情况下)这基本上会使它们在某些操作系统上得到页面文件的支持——这意味着在需要之前根本不会保留RAM(对于blob上的某些操作,比如将其转换为ArrayBuffer
)
因此,从Blob
到ArrayBuffer
的转换,虽然技术上没有指定为O(n)
,但在大多数用户代理中都是如此,因为后者有助于实际的即时读写数据访问(通过元素索引等),而
const resp = new Response(blob)
const ab = await resp.arrayBuffer()