JavaScript 中类型化数组的优点是它们在 C 中的工作方式相同或相似吗?

2024-01-08

我一直在玩类型化数组 https://developer.mozilla.org/en-US/docs/JavaScript_typed_arrays在 JavaScript 中。

var buffer = new ArrayBuffer(16);
var int32View = new Int32Array(buffer);

我想象普通数组([1, 257, true])JavaScript 中的性能很差,因为它们的值可以是任何类型,因此,达到内存中的偏移量并不是微不足道的。

我最初认为 JavaScript 数组下标的工作方式与对象相同(因为它们有很多相似之处),并且是hash map http://en.wikipedia.org/wiki/Hash_table基于,需要基于哈希的查找。但我还没有找到太多可信的信息来证实这一点。

因此,我认为类型化数组表现如此出色的原因是它们的工作方式与 C 中的普通数组类似,在 C 语言中它们始终是类型化的。给出上面的初始代码示例,并希望获得类型化数组中的第 10 个值......

var value = int32View[10];
  • 类型是Int32,所以每个值必须包含32位或4 bytes.
  • 下标是10.
  • 所以该值在内存中的位置是<array offset> + (4 * 10),然后阅读4字节来获取总值。

我基本上只是想证实我的假设。我对此的想法是否正确,如果不正确,请详细说明。

我查看了V8源码 https://github.com/v8/v8看看我自己能不能回答这个问题,但是我的C很生疏,而且我对C++也不太熟悉。


出于性能原因,类型化数组是由 WebGL 标准委员会设计的。通常,Javascript 数组是通用的,可以保存对象、其他数组等 - 并且元素在内存中不一定是连续的,就像在 C 中一样。WebGL 要求缓冲区在内存中是连续的,因为这就是底层 C API 所期望的他们。如果不使用类型化数组,则将普通数组传递给 WebGL 函数需要大量工作:必须检查每个元素,检查类型,如果它是正确的(例如浮点数),则将其复制到单独的顺序数组中类似 C 的缓冲区,然后将该顺序缓冲区传递给 C API。哎呀——工作量很大!对于性能敏感的 WebGL 应用程序,这可能会导致帧速率大幅下降。

另一方面,就像您在问题中建议的那样,类型化数组在其幕后存储中使用了类似 C 的连续缓冲区。当您写入类型化数组时,您实际上是在幕后分配给类似 C 的数组。就 WebGL 而言,这意味着相应的 C API 可以直接使用缓冲区。

请注意,您的内存地址计算还不够:浏览器must还对数组进行边界检查,以防止超出范围的访问。任何类型的 Javascript 数组都会发生这种情况,但在许多情况下,聪明的 Javascript 引擎可以在证明索引值已经在范围内时省略检查(例如从 0 循环到数组的长度)。它还必须检查数组索引是否确实是数字而不是字符串或其他内容!但本质上就像您所描述的那样,使用类似 C 的寻址。

BUT...那不是全部!在某些情况下,聪明的 Javascript 引擎可以也推导出普通Javascript数组的类型。在像 V8 这样的引擎中,如果你创建一个普通的 Javascript 数组并且只在其中存储浮点数,V8 可能会乐观地确定它是一个浮点数数组并优化它生成的代码。其性能与类型化数组相当。因此,类型化数组实际上并不是达到最大性能所必需的:只需可预测地使用数组(每个元素都具有相同类型),并且某些引擎也可以对此进行优化。

那么为什么类型化数组仍然需要存在呢?

  • 像推导数组类型这样的优化是真的很复杂。如果 V8 推断出一个普通数组中只有浮点数,那么您将一个对象存储在一个元素中,它必须去优化并重新生成使数组再次通用的代码。所有这一切都透明地进行,这是一项相当大的成就。类型化数组要简单得多:它们保证是一种类型,并且您不能在其中存储其他内容(例如对象)。
  • 优化永远不会保证发生;您可以在普通数组中仅存储浮点数,但引擎可能会出于各种原因决定不对其进行优化。
  • 事实上它们要简单得多,这意味着其他不太复杂的 JavaScript 引擎可以轻松实现它们。他们不需要所有高级的去优化支持。
  • 即使使用真正先进的引擎,证明可以使用优化也是极其困难的,有时甚至是不可能的。类型化数组显着简化了引擎需要能够围绕它进行优化的证明级别。从类型化数组返回的值肯定是某种类型,引擎可以针对该类型的结果进行优化。从普通数组返回的值理论上可以具有任何类型,并且引擎可能无法证明它总是具有相同类型的结果,因此生成效率较低的代码。因此,围绕类型化数组的代码更容易优化。
  • 类型化数组消除了犯错误的机会。您不可能意外地存储一个对象并突然获得更差的性能。

因此,简而言之,普通数组理论上可以与类型数组一样快。但类型化数组可以更轻松地达到峰值性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript 中类型化数组的优点是它们在 C 中的工作方式相同或相似吗? 的相关文章

随机推荐

  • 在Python中强制函数参数类型?

    我在 Python 类中有一个函数 可以将接口添加到列表中 def RegisterAsListener self inListener self TransitListeners append inListener 这很好 因为一个类只需
  • 在类函数中定义类函数:Python

    我有一个代码 我想在类函数中定义一个类函数 这是我想做的一个简单的例子 该程序的目标是打印 4 gt gt gt class bluh def haha self print 3 def init self def haha self pr
  • Xrm.Page.data 为空

    我在机会实体上添加了一个自定义表单 并附加了一些 javascript 我使用 window open 和 url 中的 formId 来调用表单来打开表单 并且仅用于创建机会实体 在 javascript 中 我只是尝试填充一些字段 但
  • 使用 PHP 和 HTML 时的最佳实践是什么?

    我设计网站已经有一段时间了 但在使用 PHP 和 HTML 时 有一点我一直不太确定 整个文档用 PHP 编写是不是更好 echoHTML 像这样 或者有一个像这样的 HTML 文件 然后添加到 PHP 中 div Content div
  • 人们使用类加载做什么?

    因此 每本 Java 教科书都会谈论 Java 的灵活性 因为它可以在运行时加载类 只需拼凑一根绳子并将其交给Class forName 并抓住ClassNotFoundException并处理它 理论就讲这么多 您能否举例说明如何使用 J
  • 在鼠标悬停时动态添加和删除类 - Vue.js

    我可以使用 Vue 成功地在鼠标悬停时添加一个类 但我想在鼠标离开元素时删除该类 在 Vue 中处理这个问题的惯用方法是什么
  • MongoDB $或查询

    我在 mongo shell 中运行以下查询 db Profiles find or name gary name rob 它只是按预期返回任何内容 JSON Use in 对于问题中的查询 使用更合适 in http docs mongo
  • Websocket 跨页面 JavaScript

    我用 JS 实现了一个基本的 websockets 客户端 function connectToNotifServer var conn new WebSocket ws localhost 8080 conn onopen functio
  • 管道、dup2 和 exec()

    我必须编写一个可以运行管道的外壳 例如像这样的命令ls l wc l 我已经成功解析了用户给出的命令 如下所示 ls 第一个cmd l frsarg wc scmd l secarg 现在我必须使用两个叉子 因为命令是两个和一个管道 我编写
  • XML 中真正允许的字符

    由于在解析某些 据说是 XML 数据时出现一些解析器错误 我查看了XML标准 http www w3 org TR REC xml d 找出真正允许的内容 我目前的疑虑是关于标签内容中允许包含哪些内容
  • 添加更多代码后,Google Apps 脚本会随机生成错误消息“发生意外错误”

    我编写了一个 Google Apps Script UiApp 应用程序 其中包含近 1000 行代码以及相当数量的处理程序和回调 该应用程序运行良好 但随着代码的增长 应用程序突然收到很多 发生意外错误 消息 错误消息在应用程序加载时出现
  • 您如何根据风格选择元素?

    使用 jQuery 您如何找到具有特定样式的元素 例如 float left 无论它是内联样式还是 CSS 文件中定义的样式 使用过滤功能 http docs jquery com Traversing filter filter func
  • 带有嵌套资源轨的嵌套表单 4

    我正在尝试在 Rails 4 0 3 上创建一个带有嵌套资源的嵌套 form for 但是我遇到了一些问题并且花了很多时间 问题是当我尝试提交表单时 这些值没有保存在我的数据库中 它将直接重定向到labs index 我已经定义了嵌套资源和
  • 为什么带宽以每秒位数来衡量?

    根据带宽的定义 它是频率的宽度 光谱 因此带宽应以 Hz 为单位进行测量 但 bps Mbps kbps 几乎到处都被用作带宽的度量 我需要知道的是 为什么使用 bps kbps 等数据传输速率测量来测量信号的带宽 由于对香农 哈特利定律的
  • 是的:将字段本身与另一个字段进行比较

    I had StartIntensity yup number EndIntensity yup number when StartIntensity StartIntensity number schema any gt return S
  • Rest 集合中的分页

    我有兴趣向 JSON 文档集合公开一个直接的 REST 接口 想想CouchDB http couchdb apache org or 坚持不懈 http persvr org 我遇到的问题是如何处理GET如果集合很大 则对集合根进行操作
  • Bootstrap 4.0.0 的 Jquery 兼容版本是什么

    请建议与Bootstrap版本4 0 0一起使用的jquery的兼容版本 也只是为了了解知识 列出了 bootstrap 和 Jquery 一起工作的版本 有什么建议或者参考 谢谢 Bootstrap 4 3 对导航栏菜单的创建方式进行了重
  • 带有 Html.ActionLink 的绝对(外部)URL

    我无法让 Html ActionLink 生成绝对网址 Html ActionLink DataBinder Eval c DataItem Name ToString DataBinder Eval c DataItem Path ToS
  • 使用 prometheus 统计 k8s 集群 cpu/内存使用情况

    我想用prometheus计算k8s集群cpu 内存使用情况 不是k8s pod使用情况 这样我就可以在grafana中显示 I use sum container memory usage bytes id 获取 k8s 集群使用的内存
  • JavaScript 中类型化数组的优点是它们在 C 中的工作方式相同或相似吗?

    我一直在玩类型化数组 https developer mozilla org en US docs JavaScript typed arrays在 JavaScript 中 var buffer new ArrayBuffer 16 va