Skip to content

Commit

Permalink
perf(NODE-5955): use pooled memory when possible (#653)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbbeeken authored Feb 29, 2024
1 parent 6d343ab commit 78c4264
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/bson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function serialize(object: Document, options: SerializeOptions = {}): Uin
);

// Create the final buffer
const finishedBuffer = ByteUtils.allocate(serializationIndex);
const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);

// Copy into the finished buffer
finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
Expand Down
2 changes: 1 addition & 1 deletion src/decimal128.ts
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ export class Decimal128 extends BSONValue {
}

// Encode into a buffer
const buffer = ByteUtils.allocate(16);
const buffer = ByteUtils.allocateUnsafe(16);
index = 0;

// Encode the low 64 bits of the decimal
Expand Down
2 changes: 1 addition & 1 deletion src/objectid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export class ObjectId extends BSONValue {
}

const inc = ObjectId.getInc();
const buffer = ByteUtils.allocate(12);
const buffer = ByteUtils.allocateUnsafe(12);

// 4-byte timestamp
NumberUtils.setInt32BE(buffer, 0, time);
Expand Down
24 changes: 11 additions & 13 deletions src/parser/deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ function deserializeObject(
value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
index = index + stringSize;
} else if (elementType === constants.BSON_DATA_OID) {
const oid = ByteUtils.allocate(12);
oid.set(buffer.subarray(index, index + 12));
const oid = ByteUtils.allocateUnsafe(12);
for (let i = 0; i < 12; i++) oid[i] = buffer[index + i];
value = new ObjectId(oid);
index = index + 12;
} else if (elementType === constants.BSON_DATA_INT && promoteValues === false) {
Expand Down Expand Up @@ -355,9 +355,9 @@ function deserializeObject(
}
} else if (elementType === constants.BSON_DATA_DECIMAL128) {
// Buffer to contain the decimal bytes
const bytes = ByteUtils.allocate(16);
const bytes = ByteUtils.allocateUnsafe(16);
// Copy the next 16 bytes into the bytes buffer
bytes.set(buffer.subarray(index, index + 16), 0);
for (let i = 0; i < 16; i++) bytes[i] = buffer[index + i];
// Update index
index = index + 16;
// Assign the new Decimal128 value
Expand Down Expand Up @@ -398,7 +398,6 @@ function deserializeObject(
}
}
} else {
const _buffer = ByteUtils.allocate(binarySize);
// If we have subtype 2 skip the 4 bytes for the size
if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
binarySize = NumberUtils.getInt32LE(buffer, index);
Expand All @@ -411,13 +410,12 @@ function deserializeObject(
throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
}

// Copy the data
for (i = 0; i < binarySize; i++) {
_buffer[i] = buffer[index + i];
}

if (promoteBuffers && promoteValues) {
value = _buffer;
value = ByteUtils.allocateUnsafe(binarySize);
// Copy the data
for (i = 0; i < binarySize; i++) {
value[i] = buffer[index + i];
}
} else {
value = new Binary(buffer.slice(index, index + binarySize), subType);
if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
Expand Down Expand Up @@ -616,8 +614,8 @@ function deserializeObject(
index = index + stringSize;

// Read the oid
const oidBuffer = ByteUtils.allocate(12);
oidBuffer.set(buffer.subarray(index, index + 12), 0);
const oidBuffer = ByteUtils.allocateUnsafe(12);
for (let i = 0; i < 12; i++) oidBuffer[i] = buffer[index + i];
const oid = new ObjectId(oidBuffer);

// Update the index
Expand Down
2 changes: 2 additions & 0 deletions src/utils/byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export type ByteUtils = {
toLocalBufferType(buffer: Uint8Array | ArrayBufferView | ArrayBuffer): Uint8Array;
/** Create empty space of size */
allocate: (size: number) => Uint8Array;
/** Create empty space of size, use pooled memory when available */
allocateUnsafe: (size: number) => Uint8Array;
/** Check if two Uint8Arrays are deep equal */
equals: (a: Uint8Array, b: Uint8Array) => boolean;
/** Check if two Uint8Arrays are deep equal */
Expand Down
5 changes: 5 additions & 0 deletions src/utils/node_byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type NodeJsBuffer = ArrayBufferView &
};
type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
alloc: (size: number) => NodeJsBuffer;
allocUnsafe: (size: number) => NodeJsBuffer;
from(array: number[]): NodeJsBuffer;
from(array: Uint8Array): NodeJsBuffer;
from(array: ArrayBuffer): NodeJsBuffer;
Expand Down Expand Up @@ -89,6 +90,10 @@ export const nodeJsByteUtils = {
return Buffer.alloc(size);
},

allocateUnsafe(size: number): NodeJsBuffer {
return Buffer.allocUnsafe(size);
},

equals(a: Uint8Array, b: Uint8Array): boolean {
return nodeJsByteUtils.toLocalBufferType(a).equals(b);
},
Expand Down
4 changes: 4 additions & 0 deletions src/utils/web_byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ export const webByteUtils = {
return new Uint8Array(size);
},

allocateUnsafe(size: number): Uint8Array {
return webByteUtils.allocate(size);
},

equals(a: Uint8Array, b: Uint8Array): boolean {
if (a.byteLength !== b.byteLength) {
return false;
Expand Down

0 comments on commit 78c4264

Please sign in to comment.