【问题标题】:Creating a typed array from a byte array stored as a node Buffer从存储为节点缓冲区的字节数组创建类型化数组
【发布时间】:2015-06-02 19:20:14
【问题描述】:

来自节点docs关于从缓冲区创建类型化数组:

缓冲区的内存被解释为一个数组,而不是一个字节数组。那 是,new Uint32Array(new Buffer([1,2,3,4])) 创建了一个 4 元素 Uint32Array 带有元素 [1,2,3,4],而不是带有单个元素的 Uint32Array 元素[0x1020304][0x4030201]

这与普通 javascript 不同,后者从 ArrayBuffer 创建类型化数组视图使用 ArrayBuffer 的内存作为字节(如 C++ 中的 reinterpret_cast)。在节点缓冲区上操作时,我需要节点中的这种行为。

我可以将 Buffer 转换为 ArrayBuffer,但这对我的应用程序来说太慢了。 (我尝试了很多方法——但它们都是 O(n) 时间。)(编辑:我找到的最快的方法是 this,这是一个单一的 memmove 操作并且非常快,但仍然有在释放对原始 Buffer 的引用之前,至少会消耗 2 倍的内存。)

是否有任何 (fast/O(1)) 方法从 Buffer 中获取类型化数组,使用 Buffer 的内容作为字节而不是元素?(所需的类型化数组元素大小为 > 1个字节,不用说。)

【问题讨论】:

  • 应该对数组进行什么类型的操作?如果是只读的,那为什么不直接通过偏移量来引用缓冲区中的元素呢?例如:buf.readUInt32LE(i*4) 其中i 是数组索引?
  • 我需要快速重复地遍历数组。 read* 方法真的很慢。
  • 我认为没有比这更快的地方了:如果我们需要索引的Int32值i:var k = i*4; return buf[k] | buf[k+1]<<8 | buf[k+2]<<16 | buf[k+3]<<256;
  • 我发明了一辆自行车:如果我们看一下模块buffer.js - 正是阅读的实现方式。

标签: node.js


【解决方案1】:

据我所知,如果不复制内存中的数据,就不可能做到这一点。 甚至您的示例 new Uint32Array(new Buffer([1,2,3,4])) 在内部也这样做(这意味着它不是 O(1))。

请注意,类型化数组只是ArrayBuffer视图(不是Buffer,这是不可能的)。 new Uint32Array(array) 创建 ArrayBuffer4 * array.length 字节。您可以使用uint32Array.buffer 访问它。构造函数将您的 Buffer 与普通的 Array 区别对待。

我知道的最佳解决方案是the one you already found

使用Uint32Array 进行尝试的另一个问题是depends on platform byte order。您可以像 this 一样遍历 Buffer 或使用 DataView,如果您想安全的话。

【讨论】:

    【解决方案2】:

    从节点 4.0 开始,Buffers 是 Uint8Arrays,可以直接在其上构建新视图:

    var b = new Buffer([1,2,3,4]);
    new Uint32Array(b.buffer, b.byteOffset);
    

    这个小例子假设b 大于~4096(缓冲区拥有自己的内存块与共享更大块的阈值)。请参阅Convert a binary NodeJS Buffer to JavaScript ArrayBuffer 了解更多信息——通常您应该调用b.slice() 以仅对您拥有的内存进行操作。

    【讨论】:

    • NB:new Uint32Array(b.buffer, b.byteOffset).length -> 2046 ... 不起作用。你是对的——可以直接构造,但是“as uint8array”不是字节。
    • @shaunc 确实有效,看看结果的内容。意外的长度是节点的共享数组缓冲区分配器的副作用。至少在缓冲区较小时使用b.slice,或者始终确保安全。
    • new Uint32Array(b.buffer, b.byteOffset).slice(0,4) -> Uint32Array [ 67305985, 0, 8192, 0 ] ?当我将两个“b”都重写为b.slice(0,4) 时是否相同? (注意:节点 9.3.0)哎呀......我想这是对的 :) 抱怨......在你编辑之前,我不会让我通过投票来纠正我的错误——任何编辑都可以,我会投票。对不起
    • 没有问题,已澄清。干杯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 2019-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多