1. A Buffer
é apenas uma visão para analisar um ArrayBuffer
.
A Buffer
, de fato, é a FastBuffer
, que extends
(herda de) Uint8Array
, que é uma visão da unidade de octetos ("acessador parcial") da memória real, an ArrayBuffer
.
Ode Node.js 9.4.0/lib/buffer.js#L65-L73
class FastBuffer extends Uint8Array {
constructor(arg1, arg2, arg3) {
super(arg1, arg2, arg3);
}
}
FastBuffer.prototype.constructor = Buffer;
internalBuffer.FastBuffer = FastBuffer;
Buffer.prototype = FastBuffer.prototype;
2. O tamanho de um ArrayBuffer
e o tamanho de sua visualização podem variar.
Razão # 1: Buffer.from(arrayBuffer[, byteOffset[, length]])
.
Com Buffer.from(arrayBuffer[, byteOffset[, length]])
, você pode criar um Buffer
com especificando sua posição subjacente ArrayBuffer
e a posição e tamanho da exibição.
const test_buffer = Buffer.from(new ArrayBuffer(50), 40, 10);
console.info(test_buffer.buffer.byteLength); // 50; the size of the memory.
console.info(test_buffer.length); // 10; the size of the view.
Razão # 2: FastBuffer
alocação de memória.
Ele aloca a memória de duas maneiras diferentes, dependendo do tamanho.
- Se o tamanho for menor que a metade do tamanho de um conjunto de memórias e não for 0 (“pequeno”) : ele utiliza um conjunto de memórias para preparar a memória necessária.
- Senão : ele cria um dedicado
ArrayBuffer
que se encaixa exatamente na memória necessária.
Ode Node.js 9.4.0/lib/buffer.js#L306-L320
function allocate(size) {
if (size <= 0) {
return new FastBuffer();
}
if (size < (Buffer.poolSize >>> 1)) {
if (size > (poolSize - poolOffset))
createPool();
var b = new FastBuffer(allocPool, poolOffset, size);
poolOffset += size;
alignPool();
return b;
} else {
return createUnsafeBuffer(size);
}
}
Ode Node.js 9.4.0/lib/buffer.js#L98-L100
function createUnsafeBuffer(size) {
return new FastBuffer(createUnsafeArrayBuffer(size));
}
O que você quer dizer com " pool de memória "?
Um conjunto de memórias é um bloco de memória pré-alocado de tamanho fixo para manter pequenos blocos de memória por Buffer
s. O uso mantém os blocos de memória de tamanho pequeno firmemente juntos, evitando a fragmentação causada pelo gerenciamento separado (alocação e desalocação) de blocos de memória de tamanho pequeno.
Neste caso, os pools de memória são ArrayBuffer
s cujo tamanho é de 8 KiB por padrão, que é especificado em Buffer.poolSize
. Quando é para fornecer um pedaço de memória de tamanho pequeno para a Buffer
, ele verifica se o último pool de memória possui memória disponível suficiente para lidar com isso; nesse caso, cria um Buffer
que "visualiza" o pedaço parcial fornecido do conjunto de memórias; caso contrário, cria um novo conjunto de memórias e assim por diante.
Você pode acessar o subjacente ArrayBuffer
de a Buffer
. O Buffer
's buffer
propriedade (ou seja, herdada Uint8Array
) prende-lo. Um “pequeno” Buffer
da buffer
propriedade é um ArrayBuffer
que representa todo o pool de memória. Portanto, neste caso, o ArrayBuffer
e Buffer
varia em tamanho.
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
// A `Buffer`'s `length` property holds the size, in octets, of the view.
// An `ArrayBuffer`'s `byteLength` property holds the size, in octets, of its data.
console.info(zero_sized_buffer.length); /// 0; the view's size.
console.info(zero_sized_buffer.buffer.byteLength); /// 0; the memory..'s size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
console.info(small_buffer.length); /// 3; the view's size.
console.info(small_buffer.buffer.byteLength); /// 8192; the memory pool's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
console.info(big_buffer.length); /// 4096; the view's size.
console.info(big_buffer.buffer.byteLength); /// 4096; the memory's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.
3. Portanto, precisamos extrair a memória que " visualiza ".
Como o ArrayBuffer
tamanho é fixo, precisamos extraí-lo fazendo uma cópia da peça. Para fazer isso, usamos Buffer
's byteOffset
propriedade e length
propriedade , que são herdadas Uint8Array
, e o ArrayBuffer.prototype.slice
método , que faz uma cópia de uma parte de um ArrayBuffer
. O slice()
método -ing aqui foi inspirado no @ZachB .
const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
function extract_arraybuffer(buf)
{
// You may use the `byteLength` property instead of the `length` one.
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}
// A copy -
const test_arraybuffer = extract_arraybuffer(test_buffer); // of the memory.
const zero_sized_arraybuffer = extract_arraybuffer(zero_sized_buffer); // of the... void.
const small_arraybuffer = extract_arraybuffer(small_buffer); // of the part of the memory.
const big_arraybuffer = extract_arraybuffer(big_buffer); // of the memory.
console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096
4. Melhoria de desempenho
Se você usar os resultados como somente leitura, ou se estiver modificando o Buffer
conteúdo da entrada , poderá evitar cópias desnecessárias da memória.
const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);
function obtain_arraybuffer(buf)
{
if(buf.length === buf.buffer.byteLength)
{
return buf.buffer;
} // else:
// You may use the `byteLength` property instead of the `length` one.
return buf.subarray(0, buf.length);
}
// Its underlying `ArrayBuffer`.
const test_arraybuffer = obtain_arraybuffer(test_buffer);
// Just a zero-sized `ArrayBuffer`.
const zero_sized_arraybuffer = obtain_arraybuffer(zero_sized_buffer);
// A copy of the part of the memory.
const small_arraybuffer = obtain_arraybuffer(small_buffer);
// Its underlying `ArrayBuffer`.
const big_arraybuffer = obtain_arraybuffer(big_buffer);
console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096