Resizable ArrayBuffers: redimensionando buffers binários sem copiar

Conheça os ArrayBuffers redimensionáveis do ES2024, que permitem crescer ou encolher um buffer binário no próprio local com resize() e transferir sua posse com transfer(), sem realocação manual.

Até o ES2024, um ArrayBuffer tinha um tamanho fixo desde a criação: se você precisasse de mais espaço, a única saída era alocar um buffer novo e copiar os dados antigos para dentro dele. Os resizable ArrayBuffers mudam isso, permitindo que um buffer cresça ou encolha no próprio local com resize(), além de trazer transfer() para mover a posse dos bytes entre buffers sem copiá-los.

O problema do tamanho fixo

Antes, redimensionar um buffer significava alocar um novo e copiar manualmente:

let buffer = new ArrayBuffer(16);
const view = new Uint8Array(buffer);
view.set([1, 2, 3, 4]);

// Precisa de mais espaço? Aloca outro buffer e copia tudo de novo.
const maior = new ArrayBuffer(32);
new Uint8Array(maior).set(new Uint8Array(buffer));
buffer = maior;

Isso é custoso para buffers grandes e comum em estruturas que crescem dinamicamente, como parsers de streaming, buffers de rede ou estruturas de dados binárias que não sabem o tamanho final de antemão.

Criando um buffer redimensionável

Basta passar a opção maxByteLength no construtor, definindo o limite até o qual o buffer pode crescer:

const buffer = new ArrayBuffer(16, { maxByteLength: 1024 });

console.log(buffer.byteLength);    // 16 — tamanho atual
console.log(buffer.maxByteLength); // 1024 — limite máximo
console.log(buffer.resizable);     // true

O maxByteLength precisa ser definido na criação e não pode ser alterado depois — é um teto reservado desde o início, de forma parecida com a capacidade de um ArrayList em outras linguagens.

resize(): crescendo e encolhendo no lugar

const buffer = new ArrayBuffer(16, { maxByteLength: 1024 });
const view = new Uint8Array(buffer);
view.set([10, 20, 30, 40]);

buffer.resize(8); // encolhe para 8 bytes
console.log(view.length); // a view já reflete o novo tamanho: 8

buffer.resize(64); // cresce de volta, até o limite de maxByteLength
console.log(buffer.byteLength); // 64

Uma TypedArray criada sobre o buffer sem um comprimento fixo (sem passar length no construtor) é chamada de length-tracking: ela acompanha automaticamente o tamanho atual do buffer a cada resize(), sem precisar recriar a view. Tentar redimensionar além de maxByteLength lança um RangeError.

transfer() e transferToFixedLength()

Esses métodos criam um novo ArrayBuffer com o mesmo conteúdo e detach (desconectam) o buffer original, que fica inutilizável — útil para transferir posse dos dados sem o custo de uma cópia defensiva:

const original = new ArrayBuffer(8, { maxByteLength: 32 });
new Uint8Array(original).set([1, 2, 3, 4, 5, 6, 7, 8]);

const novo = original.transfer(16); // novo buffer com 16 bytes, resizable
console.log(original.byteLength); // 0 — o original foi detachado
console.log(novo.byteLength);     // 16
console.log(novo.resizable);      // true, com o mesmo maxByteLength

const fixo = novo.transferToFixedLength(); // devolve um buffer comum, não resizable
console.log(fixo.resizable); // false

transfer() aceita um newByteLength opcional e preserva a característica resizable do buffer de origem; transferToFixedLength() sempre devolve um buffer de tamanho fixo, mesmo que o original fosse resizable.

Quando usar

Cuidado com o custo de maxByteLength

Reservar um maxByteLength muito maior do que o necessário pode levar o engine a pré-alocar memória de forma menos eficiente, dependendo da implementação. Vale definir um limite realista em vez de um valor arbitrariamente alto "só para garantir".

Compatibilidade

Resizable ArrayBuffers fazem parte do ECMAScript 2024 e têm suporte amplo nos navegadores modernos (Chrome/Edge 111+, Firefox 128+, Safari 16.4+) e no Node.js recente, desde julho de 2024. Como ainda é uma adição relativamente nova, vale confirmar o suporte antes de depender dela em ambientes mais antigos.

caniuse

Conclusão

Com resize() e transfer(), o ArrayBuffer deixa de ser uma estrutura rígida e ganha flexibilidade que antes só vinha de bibliotecas especializadas ou de código manual de realocação, tornando buffers binários dinâmicos uma operação nativa e eficiente.

Tecnologia:
js

Deixe seu Comentário!

Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.

Comentário
Nome
Email
lock Seu e-mail não será publicado.