1. A Bufferes solo una vista para mirar un ArrayBuffer.
A Buffer, de hecho, es un FastBuffer, que extends(hereda de) Uint8Array, que es una vista de unidad de octeto ("acceso parcial") de la memoria real, unArrayBuffer .
📜 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. El tamaño de an ArrayBuffery el tamaño de su vista pueden variar.
Razón # 1: Buffer.from(arrayBuffer[, byteOffset[, length]]) .
Con Buffer.from(arrayBuffer[, byteOffset[, length]]), puede crear un Buffercon especificar su subyacente ArrayBuffery la posición y el tamaño de la vista.
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ón # 2: FastBufferasignación de memoria de.
Asigna la memoria de dos formas diferentes según el tamaño.
- Si el tamaño es menor que la mitad del tamaño de un grupo de memoria y no es 0 ("pequeño") : utiliza un grupo de memoria para preparar la memoria requerida.
- De lo contrario : crea un dedicado
ArrayBufferque se ajusta exactamente a la memoria requerida.
📜 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);
}
}
📜 Node.js 9.4.0/lib/buffer.js#L98-L100
function createUnsafeBuffer(size) {
return new FastBuffer(createUnsafeArrayBuffer(size));
}
¿Qué quiere decir con un " grupo de memoria "?
Un grupo de memoria es un bloque de memoria preasignado de tamaño fijo para mantener fragmentos de memoria de tamaño pequeño durante Buffers. Su uso mantiene los fragmentos de memoria de pequeño tamaño muy juntos, por lo que evita la fragmentación. causada por la administración separada (asignación y desasignación) de fragmentos de memoria de pequeño tamaño.
En este caso, las agrupaciones de memoria son ArrayBuffers cuyo tamaño es de 8 KiB de forma predeterminada, que se especifica en Buffer.poolSize. Cuando se trata de proporcionar un fragmento de memoria de tamaño pequeño para un Buffer, comprueba si el último grupo de memoria tiene suficiente memoria disponible para manejar esto; si es así, crea un Bufferque "ve" el fragmento parcial dado del grupo de memoria, de lo contrario, crea un nuevo grupo de memoria y así sucesivamente.
Puede acceder al subyacente ArrayBufferde a Buffer. El Buffer's bufferde propiedad (es decir, heredado de Uint8Array) la sostiene. Un “pequeño” Buffer 's bufferestablecimiento es el ArrayBufferque representa la totalidad del bloque de memoria. Entonces, en este caso, el ArrayBuffery el Buffervaría en tamaño.
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. Entonces necesitamos extraer la memoria que " ve ".
Un ArrayBuffertamaño es fijo, por lo que debemos extraerlo haciendo una copia de la pieza. Para hacer esto, utilizamos Bufferla byteOffsetpropiedad y la lengthpropiedad , que se heredan Uint8Array, y el ArrayBuffer.prototype.slicemétodo , que hace una copia de una parte de un ArrayBuffer. El slice()método -ing aquí fue inspirado por @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. Mejora del rendimiento
Si va a utilizar los resultados como de solo lectura, o está bien modificar el Buffercontenido de la entrada , puede evitar la copia innecesaria de la memoria.
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