From a2e03d1d623150faefff354856079ceada0c5832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Boquet?= Date: Tue, 13 Feb 2024 21:53:35 +0000 Subject: [PATCH] improve deserialization performance by moving allocations to nested paths --- src/parser/deserializer.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/parser/deserializer.ts b/src/parser/deserializer.ts index abb61046e..2b4502972 100644 --- a/src/parser/deserializer.ts +++ b/src/parser/deserializer.ts @@ -164,7 +164,7 @@ function deserializeObject( // Reflects utf-8 validation setting regardless of global or specific key validation let validationSetting: boolean; // Set of keys either to enable or disable validation on - const utf8KeysSet = new Set(); + let utf8KeysSet; // Check for boolean uniformity and empty validation option const utf8ValidatedKeys = validation.utf8; @@ -190,6 +190,8 @@ function deserializeObject( // Add keys to set that will either be validated or not based on validationSetting if (!globalUTFValidation) { + utf8KeysSet = new Set(); + for (const key of Object.keys(utf8ValidatedKeys)) { utf8KeysSet.add(key); } @@ -216,8 +218,9 @@ function deserializeObject( let isPossibleDBRef = isArray ? false : null; + let dataView; + // While we have more left data left keep parsing - const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); while (!done) { // Read the type const elementType = buffer[index++]; @@ -240,7 +243,7 @@ function deserializeObject( // shouldValidateKey is true if the key should be validated, false otherwise let shouldValidateKey = true; - if (globalUTFValidation || utf8KeysSet.has(name)) { + if (globalUTFValidation || utf8KeysSet?.has(name)) { shouldValidateKey = validationSetting; } else { shouldValidateKey = !validationSetting; @@ -284,10 +287,12 @@ function deserializeObject( (buffer[index++] << 16) | (buffer[index++] << 24); } else if (elementType === constants.BSON_DATA_NUMBER && promoteValues === false) { - value = new Double(dataview.getFloat64(index, true)); + dataView ??= new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); + value = new Double(dataView.getFloat64(index, true)); index = index + 8; } else if (elementType === constants.BSON_DATA_NUMBER) { - value = dataview.getFloat64(index, true); + dataView ??= new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); + value = dataView.getFloat64(index, true); index = index + 8; } else if (elementType === constants.BSON_DATA_DATE) { const lowBits = @@ -300,6 +305,7 @@ function deserializeObject( (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24); + value = new Date(new Long(lowBits, highBits).toNumber()); } else if (elementType === constants.BSON_DATA_BOOLEAN) { if (buffer[index] !== 0 && buffer[index] !== 1)