1. A Bufferto tylko widok do spojrzenia na plik ArrayBuffer.
A Bufferw 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 ArrayBufferi rozmiar widoku mogą się różnić.
Powód # 1: Buffer.from(arrayBuffer[, byteOffset[, length]]).
Za pomocą Buffer.from(arrayBuffer[, byteOffset[, length]])można utworzyć Bufferz określeniem jego podstawy ArrayBufferoraz 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: FastBufferalokacja 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ą,
ArrayBufferktó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 Buffers. 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 ArrayBuffers, 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 ArrayBufferpliku Buffer. W Buffer„s buffernieruchomość (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. BufferbufferArrayBufferArrayBufferBuffer
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 ”.
ArrayBufferJest ustalona w wielkości, więc trzeba wyodrębnić ją poprzez kopię strony. Aby to zrobić, używamy Buffer„s byteOffsetwłasności i lengthwłaściwości , które są dziedziczone Uint8Array, a ten ArrayBuffer.prototype.slicesposó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ć BufferS'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);