1.A Buffer
- это просто представление для просмотра ArrayBuffer
.
A Buffer
, на самом деле это FastBuffer
, которое extends
(наследует от)Uint8Array
, который является октетом представление («частичный доступ») фактической памяти, 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.Размер ArrayBuffer
и размер его представления могут различаться.
Причина # 1: Buffer.from(arrayBuffer[, byteOffset[, length]])
.
С помощью Buffer.from(arrayBuffer[, byteOffset[, length]])
вы можете создаватьBuffer
с указанием лежащего в его основе ArrayBuffer
и положения и размера представления.
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.
Причина # 2: FastBuffer
выделение памяти.
Распределяет память вдва разных способа в зависимости от размера.
- Если размер меньше половины размера пула памяти и не равен 0 («маленький»): для подготовки необходимой памяти используется пул памяти .
- Остальное : создается выделенный
ArrayBuffer
, который точно соответствует требуемой памяти.
? /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));
}
Что вы подразумеваете под « пул памяти *»1085 *? ”
A пул памяти - фиксированный размер предварительно выделенный meБлок памяти для хранения небольших блоков памяти в течение Buffer
с.Его использование тесно связывает блоки памяти небольшого размера, предотвращая фрагментацию , вызванную раздельным управлением (выделением и освобождением) блоков памяти малого размера.
Inв этом случае пулы памяти имеют размер ArrayBuffer
с, размер которого по умолчанию составляет 8 КиБ, что указано в Buffer.poolSize
.Когда он предназначен для предоставления блока памяти небольшого размера для Buffer
, он проверяет, достаточно ли у последнего пула памяти доступной памяти для обработки этого;если это так, он создает Buffer
, который «просматривает» данный частичный фрагмент пула памяти, в противном случае он создает новый пул памяти и т. д.
Youможет получить доступ к базовому ArrayBuffer
из Buffer
.Свойство Buffer
buffer
(то есть наследуемое от Uint8Array
) содержит его. A «small» Buffer
s 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);
// 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.Поэтому нам нужно извлечь память, которую он « views .»
. ArrayBuffer
имеет фиксированный размер, поэтому нам нужно извлечь его, сделав копию части.Для этого мы используем Buffer
byteOffset
свойство и length
свойство , которые наследуются от Uint8Array
, а - метод ArrayBuffer.prototype.slice
, который делает копию части ArrayBuffer
.Метод slice()
-ing здесь был вдохновлен @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.Улучшение производительности
Если вы хотите использовать результаты только для чтения или если можно изменить Buffer
s , вы можете избежать ненужного копирования в память.
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