1. A Buffer
es 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 ArrayBuffer
y 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 Buffer
con especificar su subyacente ArrayBuffer
y 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: FastBuffer
asignació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
ArrayBuffer
que 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 Buffer
s. 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 ArrayBuffer
s 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 Buffer
que "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 ArrayBuffer
de a Buffer
. El Buffer
's buffer
de propiedad (es decir, heredado de Uint8Array
) la sostiene. Un “pequeño” Buffer
's buffer
establecimiento es el ArrayBuffer
que representa la totalidad del bloque de memoria. Entonces, en este caso, el ArrayBuffer
y el Buffer
varí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 ArrayBuffer
tamaño es fijo, por lo que debemos extraerlo haciendo una copia de la pieza. Para hacer esto, utilizamos Buffer
la byteOffset
propiedad y la length
propiedad , que se heredan Uint8Array
, y el ArrayBuffer.prototype.slice
mé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 Buffer
contenido 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