1. A Buffer
chỉ 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 ArrayBuffer
và 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 Buffer
chỉ định bên dưới ArrayBuffer
và 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: FastBuffer
cấ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
ArrayBuffer
phù 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 Buffer
s. 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à ArrayBuffer
s 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ở ArrayBuffer
của a Buffer
. Các Buffer
's buffer
tà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ố buffer
là một ArrayBuffer
đại diện cho toàn bộ bộ nhớ. Vì vậy, trong trường hợp này, ArrayBuffer
và Buffer
kí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 byteOffset
tài sản và length
bất động sản , được thừa hưởng từ Uint8Array
, và các ArrayBuffer.prototype.slice
phươ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 Buffer
nộ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