1. A Buffer
est juste un voir pour avoir examiné un ArrayBuffer
.
A Buffer
en fait, c'est un FastBuffer
qui extends
(hérite de) Uint8Array
qui est une unité d'octet voir (" accesseur partiel ") de la mémoire réelle, un ArrayBuffer
.
/lib/buffer.js#L65-L73
Node.js 9.4.0
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 son voir peut varier.
Raison n°1 : Buffer.from(arrayBuffer[, byteOffset[, length]])
.
Avec Buffer.from(arrayBuffer[, byteOffset[, length]])
vous pouvez créer un Buffer
avec la spécification de son sous-jacent ArrayBuffer
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
de l'allocation de mémoire.
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'une réserve de mémoire et n'est pas égal à 0 ("petit") il fait appel à une réserve de mémoire pour préparer la mémoire requise.
-
Else il crée un espace dédié
ArrayBuffer
qui correspond exactement à la mémoire requise.
/lib/buffer.js#L306-L320
Node.js 9.4.0
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);
}
}
/lib/buffer.js#L98-L100
Node.js 9.4.0
function createUnsafeBuffer(size) {
return new FastBuffer(createUnsafeArrayBuffer(size));
}
Que voulez-vous dire par un " réserve de mémoire ?"
A réserve de mémoire est une taille fixe préaffecté bloc de mémoire permettant de conserver des morceaux de mémoire de petite taille pour Buffer
s. En l'utilisant, on maintient les petits morceaux de mémoire serrés les uns contre les autres, ce qui empêche les fragmentation causée par la gestion séparée (allocation et désallocation) de morceaux de mémoire de petite taille.
Dans ce cas, les pools de mémoire sont ArrayBuffer
dont la taille est de 8 KiB par défaut, ce qui est spécifié dans le fichier Buffer.poolSize
. Quand il s'agit de fournir un morceau de mémoire de petite taille pour une Buffer
il vérifie si le dernier pool de mémoire a suffisamment de mémoire disponible pour gérer cette opération ; si c'est le cas, il crée un fichier Buffer
que "vues" le morceau 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 à la base de données ArrayBuffer
d'un Buffer
. El Buffer
's buffer
propriété (c'est-à-dire hérité de Uint8Array
) le tient. A "petit" Buffer
's buffer
est un ArrayBuffer
qui représente l'ensemble de la mémoire. Donc dans ce cas, le ArrayBuffer
y el Buffer
varie en taille.
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 " vues ."
Un site ArrayBuffer
est de taille fixe, nous devons donc l'extraire en faisant une copie de la pièce. Pour ce faire, nous utilisons Buffer
's byteOffset
propriété y length
propriété qui sont héritées de Uint8Array
y le site ArrayBuffer.prototype.slice
méthode qui fait une copie d'une partie d'un fichier ArrayBuffer
. El slice()
-La méthode utilisée 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 devez utiliser les résultats en lecture seule, ou si vous pouvez modifier l'entrée Buffer
Contenu des "s vous pouvez éviter de copier inutilement 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.bytLength)
{
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
1 votes
Je suis curieux de savoir pourquoi vous avez besoin de faire ça ?
16 votes
Un bon exemple serait d'écrire une bibliothèque qui fonctionne avec les fichiers dans les navigateurs et aussi pour les fichiers NodeJS ?
1 votes
Ou en utilisant une bibliothèque de navigateur dans NodeJS
1 votes
Une autre raison est qu'un flottant prend trop d'octets de RAM lorsqu'il est stocké dans un fichier
Array
. Ainsi, pour stocker plusieurs flottants, il fautFloat32Array
où il prend 4 octets. Et si vous voulez une sérialisation rapide de ces flottants vers un fichier, vous avez besoin d'une fonctionBuffer
car la sérialisation en JSON prend du temps.0 votes
Je veux savoir exactement la même chose pour envoyer des données génériques en utilisant WebRTC et c'est incroyable que tant de réponses ici ont tant de likes, mais ne répondent pas à la question réelle....
1 votes
const file = fs.readFileSync(filePath);
alors comment je dois utiliser ça ?... 30 minutes plus tard, wow C me manque.