ArrayBuffer.transfer strawman

November 13, 2014 ยท View on GitHub

Proposal

The proposal is to add a static ArrayBuffer.transfer(oldBuffer [, newByteLength]). This method returns a new ArrayBuffer whose contents are taken from oldBuffer.[[ArrayBufferData]] and then either truncated or zero-extended to be newByteLength. This operation leaves oldBuffer in a detached state. If newByteLength is undefined, oldBuffer.byteLength is used.

var buf1 = new ArrayBuffer(40); new Int32Array(buf1)[0] = 42;

var buf2 = ArrayBuffer.transfer(buf1, 80); assert(buf1.byteLength == 0); assert(buf2.byteLength == 80); assert(new Int32Array(buf2)[0] == 42);

var buf3 = ArrayBuffer.transfer(buf2, 0); assert(buf2.byteLength == 0); assert(buf3.byteLength == 0);

Motivation

This proposal gives JS developers several new memory management powers:

  • The ability to detach an ArrayBuffer (with the assumption that the implementation will release the backing memory). Currently, JS programs have to drop all references and wait for finalization. In a tight 32-bit address space (or even 64-bit on mobile without paging) this explicit control can be used to avoid accidental (and non-deterministic, because of finalization) out-of-memory conditions.

  • The ability to grow an ArrayBuffer without copying, in the same manner as realloc. The advantage over copying is:

  • realloc can be two orders of magnitude faster for large buffers (because realloc doesn't need to copy, it can remap pages)
  • realloc can avoid out-of-memory in a fragmented 32-bit address space since realloc is

Any JS program that needs to manipulate large ArrayBuffers efficiently and/or work reliably within a 32-bit address space (particularly if the address space is shared with other libraries, iframes or tabs) could benefit from these added capabilities. Emscripten-ported applications are a concrete example of this.

Implementation

Since this function is semantically just copying and detaching, it should be fairly easy to implement without any broader impact on the engine.

(Credit goes to Dmitry Lomov for proposing ArrayBuffer.transfer as an alternative to ArrayBuffer.prototype.resize)