gpt4 book ai didi

javascript - 类型化数组与字符串的内存开销

转载 作者:IT王子 更新时间:2023-10-28 23:32:36 25 4
gpt4 key购买 nike

我正在尝试减少 JavaScript Web 应用程序的内存使用量,该应用程序以大量小字符串的形式在内存中存储大量信息。当我将代码更改为使用 Uint8Array 而不是 String 时,我注意到内存使用量上升了。

例如,考虑以下创建许多小字符串的代码:

// (1000000 strings) x (10 characters)
var a=[];
for (let i=0; i<1000000; i++)
a.push("a".repeat(10).toUpperCase());

如果您将它放在一个空白页面中并让内存使用量稳定几秒钟,它会在 Google Chrome 上稳定在 70 MiB。另一方面,以下代码:

// (1000000 arrays) x (10 bytes)
var a=[];
for (let i=0; i<1000000; i++)
a.push(new Uint8Array(10));

使用 233 MiB 的内存。没有任何代码的空白页面使用大约 20 MiB。另一方面,如果我创建少量大字符串/数组,差异会变得更小,并且对于具有 10000000 个字符/条目的单个字符串/数组,内存使用量几乎相同。

那么为什么类型化数组会有这么大的内存开销呢?

最佳答案

V8 开发人员在这里。您的结论是有道理的:如果您将字符串中的字符与 Uint8Array 中的元素进行比较,则字符串的开销会更少。 TypedArrays 非常擅长提供对类型化元素的快速访问;然而,拥有大量小型 TypedArray 的内存效率并不高。

区别在于字符串和类型化数组的对象 header 大小。

对于一个字符串,对象头是:

  1. 隐藏类指针
  2. 哈希
  3. 长度
  4. 有效负载

有效负载四舍五入到指针大小对齐,在这种情况下为 16 个字节。

对于 Uint8Array,您需要以下内容:

  1. 隐藏类指针

  2. 属性指针(未使用)

  3. 元素指针(见下文)

  4. 数组缓冲区指针(见下文)

  5. 数组缓冲区的偏移量

  6. 字节长度

  7. 数组缓冲区的 View 长度

  8. 长度(用户可见)

  9. 嵌入字段#1

  10. 嵌入字段#2

  11. 数组缓冲区:隐藏类指针

  12. 数组缓冲区:属性指针(未使用)

  13. 数组缓冲区:元素指针(见下文)

  14. 数组缓冲区:字节长度

  15. 数组缓冲区:后备存储

  16. 数组缓冲区:分配基数

  17. 数组缓冲区:分配长度

  18. 数组缓冲区:位域(内部标志)

  19. 数组缓冲区:嵌入字段 #1

  20. 数组缓冲区:嵌入字段#2

  21. 元素对象:隐藏类指针

  22. 元素对象:长度(后备存储)

  23. 元素对象:(后备存储的)基指针

  24. 元素对象:数据开始的偏移量

  25. 元素对象:有效载荷

同样,有效负载被四舍五入到指针大小对齐,因此在这里消耗 16 个字节。

总而言之,每个字符串消耗 5*8 = 40 字节,每个类型化数组消耗 26*8 = 208 字节。这看起来确实有很多开销。原因在于 TypedArrays 提供的各种灵活选项(它们可以将 View 重叠到 ArrayBuffers 中,可以直接从 JavaScript 分配,或与 WebGL 等共享)。

(这不是关于“优化内存分配”,也不是“更好地收集垃圾字符串”——因为你持有所有对象,GC 不会发挥作用。)

关于javascript - 类型化数组与字符串的内存开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45803829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com