1. A Bufferchỉ là một cái nhìn để nhìn vào một ArrayBuffer.
A Buffer, trên thực tế, là một FastBuffer, extends(kế thừa từ) Uint8Array, là một khung nhìn đơn vị octet (một phần truy cập một phần của bộ nhớ) của bộ nhớ thực, một 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. Kích thước của một ArrayBuffervà kích thước của khung nhìn của nó có thể thay đổi.
Lý do số 1 : Buffer.from(arrayBuffer[, byteOffset[, length]]).
Với Buffer.from(arrayBuffer[, byteOffset[, length]]), bạn có thể tạo một Bufferchỉ định bên dưới ArrayBuffervà vị trí và kích thước của khung nhìn.
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.
Lý do # 2: FastBuffercấp phát bộ nhớ.
Nó phân bổ bộ nhớ theo hai cách khác nhau tùy thuộc vào kích thước.
- Nếu kích thước nhỏ hơn một nửa kích thước của nhóm bộ nhớ và không bằng 0 (có nghĩa là nhỏ) : nó sử dụng nhóm bộ nhớ để chuẩn bị bộ nhớ cần thiết.
- Khác : nó tạo ra một chuyên dụng
ArrayBufferphù hợp chính xác với bộ nhớ cần thiết.
📜 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));
}
Bạn có ý nghĩa gì với một nhóm bộ nhớ của người Viking ?
Nhóm bộ nhớ là khối bộ nhớ được phân bổ trước có kích thước cố định để giữ các khối bộ nhớ kích thước nhỏ cho Buffers. Sử dụng nó giữ các khối bộ nhớ kích thước nhỏ lại với nhau chặt chẽ, do đó ngăn ngừa sự phân mảnh gây ra bởi quản lý riêng biệt (phân bổ và phân bổ) các khối bộ nhớ kích thước nhỏ.
Trong trường hợp này, các nhóm bộ nhớ là ArrayBuffers có kích thước là 8 KiB theo mặc định, được chỉ định trong Buffer.poolSize. Khi cần cung cấp một đoạn bộ nhớ kích thước nhỏ cho a Buffer, nó sẽ kiểm tra xem nhóm bộ nhớ cuối có đủ bộ nhớ khả dụng để xử lý việc này hay không; nếu vậy, nó tạo ra một lượt xemBuffer mà Viking xem một phần nhất định của nhóm bộ nhớ, nếu không, nó tạo ra một nhóm bộ nhớ mới, v.v.
Bạn có thể truy cập vào cơ sở ArrayBuffercủa a Buffer. Các Buffer's buffertài sản (có nghĩa là, thừa hưởng từ Uint8Array) nắm giữ nó. Một tài sản nhỏ Buffer của thành phố bufferlà một ArrayBufferđại diện cho toàn bộ bộ nhớ. Vì vậy, trong trường hợp này, ArrayBuffervà Bufferkích thước khác nhau.
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. Vì vậy, chúng tôi cần giải nén bộ nhớ mà nó xem .
An ArrayBufferđược cố định về kích thước, vì vậy chúng ta cần trích xuất nó bằng cách tạo một bản sao của bộ phận. Để làm điều này, chúng tôi sử dụng Buffer's byteOffsettài sản và lengthbất động sản , được thừa hưởng từ Uint8Array, và các ArrayBuffer.prototype.slicephương pháp , mà làm cho một bản sao của một phần của một ArrayBuffer. Các slice()phương pháp -ing ở đây được lấy cảm hứng từ @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. Cải thiện hiệu suất
Nếu bạn sử dụng kết quả dưới dạng chỉ đọc hoặc sửa đổi Buffernội dung của đầu vào , bạn có thể tránh sao chép bộ nhớ không cần thiết.
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