From 48ed47ec192416e86762527cf3beabb4a634ac93 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Mon, 11 Nov 2024 14:32:28 -0500 Subject: [PATCH] perf(NODE-6525): remove setPrototype and defineProperty from hot path (#4321) --- src/sessions.ts | 44 ++++++++-------------------- test/benchmarks/driverBench/index.js | 2 +- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/sessions.ts b/src/sessions.ts index c53bc2e485..26c829f4ac 100644 --- a/src/sessions.ts +++ b/src/sessions.ts @@ -137,7 +137,7 @@ export class ClientSession * initially undefined. Gets set to false when startTransaction is called. When commitTransaction is sent to server, if the commitTransaction succeeds, it is then set to undefined, otherwise, set to true */ commitAttempted?: boolean; /** @internal */ - [kServerSession]: ServerSession | null; + private [kServerSession]: ServerSession | null; /** @internal */ [kSnapshotTime]?: Timestamp; /** @internal */ @@ -299,11 +299,8 @@ export class ClientSession if (serverSession != null) { // release the server session back to the pool this.sessionPool.release(serverSession); - // Make sure a new serverSession never makes it onto this ClientSession - Object.defineProperty(this, kServerSession, { - value: ServerSession.clone(serverSession), - writable: false - }); + // Store a clone of the server session for reference (debugging) + this[kServerSession] = new ServerSession(serverSession); } // mark the session as ended, and emit a signal this.hasEnded = true; @@ -973,7 +970,16 @@ export class ServerSession { isDirty: boolean; /** @internal */ - constructor() { + constructor(cloned?: ServerSession | null) { + if (cloned != null) { + const idBytes = Buffer.allocUnsafe(16); + idBytes.set(cloned.id.id.buffer); + this.id = { id: new Binary(idBytes, cloned.id.id.sub_type) }; + this.lastUse = cloned.lastUse; + this.txnNumber = cloned.txnNumber; + this.isDirty = cloned.isDirty; + return; + } this.id = { id: new Binary(uuidV4(), Binary.SUBTYPE_UUID) }; this.lastUse = now(); this.txnNumber = 0; @@ -994,30 +1000,6 @@ export class ServerSession { return idleTimeMinutes > sessionTimeoutMinutes - 1; } - - /** - * @internal - * Cloning meant to keep a readable reference to the server session data - * after ClientSession has ended - */ - static clone(serverSession: ServerSession): Readonly { - const arrayBuffer = new ArrayBuffer(16); - const idBytes = Buffer.from(arrayBuffer); - idBytes.set(serverSession.id.id.buffer); - - const id = new Binary(idBytes, serverSession.id.id.sub_type); - - // Manual prototype construction to avoid modifying the constructor of this class - return Object.setPrototypeOf( - { - id: { id }, - lastUse: serverSession.lastUse, - txnNumber: serverSession.txnNumber, - isDirty: serverSession.isDirty - }, - ServerSession.prototype - ); - } } /** diff --git a/test/benchmarks/driverBench/index.js b/test/benchmarks/driverBench/index.js index 928ba31bd8..570b2feeb8 100644 --- a/test/benchmarks/driverBench/index.js +++ b/test/benchmarks/driverBench/index.js @@ -95,7 +95,7 @@ benchmarkRunner args: Object.fromEntries( Object.entries(MONGODB_CLIENT_OPTIONS).map(([key, value]) => [ key, - typeof value === 'number' ? value | 0 : value ? 1 : 0 + typeof value === 'number' ? value : value ? 1 : 0 ]) ) },