Butecho

PaposPetisco

postMessage: transfira, não copie

Um segundo argumento no postMessage evita copiar centenas de MB entre a página e o Web Worker.

João · · 1 min de leitura

Quando você manda um objeto pra um Web Worker com postMessage, o navegador faz uma cópia estruturada dele. Pra um JSON pequeno, tanto faz. Pra um PDF de 266 MB, você acabou de alocar mais 266 MB e gastar tempo copiando byte por byte.

O postMessage aceita um segundo argumento: a lista de objetos transferíveis. Um ArrayBuffer nessa lista não é copiado. A posse dele passa pro outro lado.

No Compacta PDF, a página lê o arquivo e entrega o buffer pro worker assim:

const buffer = await job.file.arrayBuffer();
worker.postMessage(
  { type: 'compress', id: job.id, buffer, preset: job.preset },
  [buffer],
);

Depois dessa linha, o buffer na página fica com byteLength igual a zero. Ele foi “desanexado”. Se você tentar ler, não tem nada lá. É o preço: um lado só pode usar a memória por vez.

Na volta é igual, com um cuidado a mais. O resultado chega como Uint8Array, e um Uint8Array pode ser só uma vista sobre um ArrayBuffer maior. O que se transfere é o buffer, não a vista. Se a vista cobrir só um pedaço, você manda o buffer inteiro junto. Então o worker recorta exatamente os bytes do arquivo antes de transferir:

const out = output.buffer.slice(
  output.byteOffset,
  output.byteOffset + output.byteLength,
);
postMessage({ type: 'done', id, buffer: out }, [out]);

O slice faz uma cópia, mas só do resultado, que já está compactado. É um seguro barato: funciona do mesmo jeito seja a vista do tamanho exato do buffer ou não.

Regra de bolso: se o que você está mandando pro worker é grande e você não vai mais usar do lado de cá, coloque na lista de transferíveis.

A saideira

Sai pelo Substack. Dá pra cancelar quando quiser.

Mais papo na mesa

Causo

Abrindo as portas

O que é o Butecho, de onde veio o nome e o que vai rolar por aqui.

5 nov 2026 · 1 min

balcãoCtrl K
$ echo "puxa uma cadeira"
puxa uma cadeira
Terminal de verdade: digita help ou usa um atalho.