1. A Buffer
est juste une vue pour regarder dans un fichier ArrayBuffer
.
A Buffer
, en fait, est a FastBuffer
, qui extends
(hérite de) Uint8Array
, qui est une vue d' unité d'octet («accesseur partiel») de la mémoire réelle, an ArrayBuffer
.
📜 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. La taille d'un ArrayBuffer
et la taille de sa vue peuvent varier.
Raison n ° 1: Buffer.from(arrayBuffer[, byteOffset[, length]])
.
Avec Buffer.from(arrayBuffer[, byteOffset[, length]])
, vous pouvez créer un Buffer
avec en spécifiant son sous ArrayBuffer
- jacent ainsi que la position et la taille de la vue.
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.
Raison n ° 2: FastBuffer
l'allocation de mémoire de.
Il alloue la mémoire de deux manières différentes en fonction de la taille.
- Si la taille est inférieure à la moitié de la taille d'un pool de mémoire et n'est pas 0 («petit») : il utilise un pool de mémoire pour préparer la mémoire requise.
- Sinon : il crée un dédié
ArrayBuffer
qui correspond exactement à la mémoire requise.
📜 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'entendez-vous par « pool de mémoire »?
Un pool de mémoire est un bloc de mémoire pré-alloué de taille fixe pour conserver des blocs de mémoire de petite taille pendant Buffer
s. Son utilisation permet de maintenir les blocs de mémoire de petite taille étroitement ensemble, évitant ainsi la fragmentation causée par la gestion séparée (allocation et désallocation) des blocs de mémoire de petite taille.
Dans ce cas, les pools de mémoire sont des ArrayBuffer
s dont la taille par défaut est de 8 Kio, ce qui est spécifié dans Buffer.poolSize
. Lorsqu'il doit fournir un bloc de mémoire de petite taille pour a Buffer
, il vérifie si le dernier pool de mémoire dispose de suffisamment de mémoire disponible pour gérer cela; si c'est le cas, il crée un Buffer
qui «visualise» le bloc partiel donné du pool de mémoire, sinon, il crée un nouveau pool de mémoire et ainsi de suite.
Vous pouvez accéder au sous-jacent ArrayBuffer
d'un Buffer
. La propriétéBuffer
s (c'est-à-dire héritée de ) la détient. Un « petit » de propriété est un qui représente l'ensemble du pool de mémoire. Donc, dans ce cas, le et le varient en taille.buffer
Uint8Array
Buffer
buffer
ArrayBuffer
ArrayBuffer
Buffer
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. Nous devons donc extraire la mémoire qu'il « visualise ».
An ArrayBuffer
est de taille fixe, nous devons donc l'extraire en faisant une copie de la pièce. Pour ce faire, nous utilisons Buffer
la byteOffset
propriété et la length
propriété de , qui sont héritées de Uint8Array
, et la ArrayBuffer.prototype.slice
méthode , qui fait une copie d'une partie d'un fichier ArrayBuffer
. La slice()
méthode -ing ici a été inspirée par @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. Amélioration des performances
Si vous utilisez les résultats en lecture seule ou siBuffer
vous pouvez modifier le contenu des entrées , vous pouvez éviter une copie inutile de la mémoire.
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