0

我在内存分配方面遇到问题,并且在网上找不到任何关于此案例的参考资料。特别是,如果我分配一个包含 65536 个元素(不是字节)或更多元素的数组,任何后续分配(即使是很小的一个)都会“失败”——当它成功执行时,它会返回一个与最近分配的数组重叠的指针。

我正在使用数组。我不确定在这里使用 StaticArray、Array 或 Float32Array 是否会改变行为,但我已经尝试了所有这些,但似乎没有得到任何改进。

汇编脚本:

export function empty(): t {
  return new Array<f32>(16)
}

export function makeArray(count: u32): arr {
  let arr = new Array<f32>(count * 16)
  let j: u32

  for (let i: u32 = 0; i < count; i++) {
    for (j = 0; j < 16; j++) {
      //logU32(i * 16 + j)
      arr[i * 16 + j] = j as f32 + 1;
    }
  }

  return arr
}

主机JS:

console.log("memory.buffer.byteLength",LinAlg.memory.buffer.byteLength)
matrixBuffer = LinAlg.Matrix4.makeArray(6000)
console.log("matrixBuffer pointer", matrixBuffer)
console.log("empty pointer", LinAlg.Matrix4.empty())

我的脚本中的一些相关日志记录:

  • memory.buffer.byteLength(登录 JS):655,360
  • 请求分配一个包含多少个元素的数组(在 WASM 中登录):96,000
  • 初始化每个缓冲区后的 Array.length(登录 WASM):96,000
  • 返回给 JS 的指针值:21216
  • 随后分配的 16 元素数组的指针值:21,216

如果我不分配第二个数组,则原始数组可通过 __getArrayView() 在 JS 中用作 96,000 个元素的数组。就好像分配大数组有效,但会破坏内存分配器以进行任何后续操作。

理论上,我应该在堆中达到 byte (21,216 + 4 * 96,000) = 405,216,并且还剩下大约 250k 的内存。

提前感谢您提供的任何帮助!

4

1 回答 1

0

来自 AssemblyScript Discord 上的 dcode:

听起来初始数组被 GC 过早收集(另一个分配可能会触发 GC 步骤),可能是因为数组既没有从 Wasm 内部引用,也没有在外部 __pined?

我可以确认将分配行更改为:

matrixBuffer = LinAlg.__pin(LinAlg.Matrix4.makeArray(6000))

修复了这个。

于 2021-08-20T22:07:25.737 回答