1. A Buffer
to tylko widok do spojrzenia na plik ArrayBuffer
.
A Buffer
w rzeczywistości jest a FastBuffer
, który extends
(dziedziczy po) Uint8Array
, który jest widokiem jednostki oktetu („częściowy akcesor”) rzeczywistej pamięci, 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. Rozmiar ArrayBuffer
i rozmiar widoku mogą się różnić.
Powód # 1: Buffer.from(arrayBuffer[, byteOffset[, length]])
.
Za pomocą Buffer.from(arrayBuffer[, byteOffset[, length]])
można utworzyć Buffer
z określeniem jego podstawy ArrayBuffer
oraz położenia i rozmiaru widoku.
const test_buffer = Buffer.from(new ArrayBuffer(50), 40, 10);
console.info(test_buffer.buffer.byteLength);
console.info(test_buffer.length);
Powód 2: FastBuffer
alokacja pamięci.
Alokuje pamięć na dwa różne sposoby w zależności od rozmiaru.
- Jeśli rozmiar jest mniejszy niż połowa wielkości puli pamięci i nie wynosi 0 („mały”) : wykorzystuje pulę pamięci do przygotowania wymaganej pamięci.
- W przeciwnym razie : tworzy dedykowaną,
ArrayBuffer
która dokładnie pasuje do wymaganej pamięci.
📜 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));
}
Co masz na myśli mówiąc „ pula pamięci ”?
Puli pamięci jest stałym rozmiarze wstępnie przyznane blok pamięci do przechowywania małych rozmiarów kawałki pamięci dla Buffer
s. Użycie go utrzymuje małe fragmenty pamięci ściśle ze sobą, dzięki czemu zapobiega fragmentacji spowodowanej oddzielnym zarządzaniem (alokacją i zwalnianiem) małych fragmentów pamięci.
W tym przypadku pule pamięci to ArrayBuffer
s, których rozmiar domyślnie wynosi 8 KB, który jest określony w Buffer.poolSize
. Kiedy ma zapewnić niewielki fragment pamięci dla a Buffer
, sprawdza, czy ostatnia pula pamięci ma wystarczającą ilość dostępnej pamięci, aby to obsłużyć; jeśli tak, to tworzy Buffer
, że „poglądy” dana częściowy klocek puli pamięci, w przeciwnym razie tworzy nową pulę pamięci i tak dalej.
Możesz uzyskać dostęp do podstawy ArrayBuffer
pliku Buffer
. W Buffer
„s buffer
nieruchomość (czyli odziedziczone Uint8Array
) trzyma go. „Mały” jest nieruchomość jest że reprezentuje całą pulę pamięci. Więc w tym przypadku, i różnią się rozmiarem. 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);
console.info(zero_sized_buffer.length);
console.info(zero_sized_buffer.buffer.byteLength);
console.info(Buffer.poolSize);
console.info(small_buffer.length);
console.info(small_buffer.buffer.byteLength);
console.info(Buffer.poolSize);
console.info(big_buffer.length);
console.info(big_buffer.buffer.byteLength);
console.info(Buffer.poolSize);
3. Więc musimy wyodrębnić pamięci „ widoki ”.
ArrayBuffer
Jest ustalona w wielkości, więc trzeba wyodrębnić ją poprzez kopię strony. Aby to zrobić, używamy Buffer
„s byteOffset
własności i length
właściwości , które są dziedziczone Uint8Array
, a ten ArrayBuffer.prototype.slice
sposób , co sprawia, kopię część kontroli ArrayBuffer
. Przedstawiona slice()
tutaj metoda -ing została zainspirowana @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)
{
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}
const test_arraybuffer = extract_arraybuffer(test_buffer);
const zero_sized_arraybuffer = extract_arraybuffer(zero_sized_buffer);
const small_arraybuffer = extract_arraybuffer(small_buffer);
const big_arraybuffer = extract_arraybuffer(big_buffer);
console.info(test_arraybuffer.byteLength);
console.info(zero_sized_arraybuffer.byteLength);
console.info(small_arraybuffer.byteLength);
console.info(big_arraybuffer.byteLength);
4. Poprawa wydajności
Jeśli jesteś wykorzystanie wyników jako tylko do odczytu, czy to jest w porządku, aby zmodyfikować wprowadzić Buffer
S'zawartość , można uniknąć niepotrzebnego kopiowania pamięci.
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;
}
return buf.subarray(0, buf.length);
}
const test_arraybuffer = obtain_arraybuffer(test_buffer);
const zero_sized_arraybuffer = obtain_arraybuffer(zero_sized_buffer);
const small_arraybuffer = obtain_arraybuffer(small_buffer);
const big_arraybuffer = obtain_arraybuffer(big_buffer);
console.info(test_arraybuffer.byteLength);
console.info(zero_sized_arraybuffer.byteLength);
console.info(small_arraybuffer.byteLength);
console.info(big_arraybuffer.byteLength);