From 3a7c7987f1066cac9d8efb374901b50fa3523c4a Mon Sep 17 00:00:00 2001 From: Jizu Sun Date: Sun, 3 Nov 2019 19:45:32 +0800 Subject: [PATCH 1/3] buffer: improve performance caused by primordials This is my first PR, and it's based on the code-and-learn guidances This restore some performance after introducing primordialias. Fixes: https://github.com/nodejs/node/issues/29766 Refs: https://github.com/nodejs/code-and-learn/issues/97 Refs: https://github.com/nodejs/node/pull/29633 --- lib/buffer.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index ce2d7c63b5b911..2ef6ef47fc9451 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -21,7 +21,8 @@ 'use strict'; -const { Math, Object } = primordials; +const { Object: { defineProperties, defineProperty, setPrototypeOf, create } } = primordials; +const { Math: { floor, trunc, min } } = primordials; const { byteLengthUtf8, @@ -89,7 +90,7 @@ FastBuffer.prototype.constructor = Buffer; Buffer.prototype = FastBuffer.prototype; addBufferPrototypeMethods(Buffer.prototype); -const constants = Object.defineProperties({}, { +const constants = defineProperties({}, { MAX_LENGTH: { value: kMaxLength, writable: false, @@ -111,7 +112,7 @@ let poolSize, poolOffset, allocPool; // do not own the ArrayBuffer allocator. Zero fill is always on in that case. const zeroFill = bindingZeroFill || [0]; -const encodingsMap = Object.create(null); +const encodingsMap = create(null); for (let i = 0; i < encodings.length; ++i) encodingsMap[encodings[i]] = i; @@ -168,7 +169,7 @@ function toInteger(n, defaultVal) { if (!Number.isNaN(n) && n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER) { - return ((n % 1) === 0 ? n : Math.floor(n)); + return ((n % 1) === 0 ? n : floor(n)); } return defaultVal; } @@ -253,7 +254,7 @@ function Buffer(arg, encodingOrOffset, length) { return Buffer.from(arg, encodingOrOffset, length); } -Object.defineProperty(Buffer, Symbol.species, { +defineProperty(Buffer, Symbol.species, { enumerable: false, configurable: true, get() { return FastBuffer; } @@ -311,7 +312,7 @@ const of = (...items) => { }; Buffer.of = of; -Object.setPrototypeOf(Buffer, Uint8Array); +setPrototypeOf(Buffer, Uint8Array); // The 'assertSize' method will remove itself from the callstack when an error // occurs. This is done simply to keep the internal details of the @@ -364,8 +365,8 @@ function SlowBuffer(length) { return createUnsafeBuffer(length); } -Object.setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); -Object.setPrototypeOf(SlowBuffer, Uint8Array); +setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); +setPrototypeOf(SlowBuffer, Uint8Array); function allocate(size) { if (size <= 0) { @@ -712,7 +713,7 @@ function byteLength(string, encoding) { Buffer.byteLength = byteLength; // For backwards compatibility. -Object.defineProperty(Buffer.prototype, 'parent', { +defineProperty(Buffer.prototype, 'parent', { enumerable: true, get() { if (!(this instanceof Buffer)) @@ -720,7 +721,7 @@ Object.defineProperty(Buffer.prototype, 'parent', { return this.buffer; } }); -Object.defineProperty(Buffer.prototype, 'offset', { +defineProperty(Buffer.prototype, 'offset', { enumerable: true, get() { if (!(this instanceof Buffer)) @@ -789,7 +790,7 @@ let INSPECT_MAX_BYTES = 50; // Override how buffers are presented by util.inspect(). Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { const max = INSPECT_MAX_BYTES; - const actualMax = Math.min(max, this.length); + const actualMax = min(max, this.length); const remaining = this.length - max; let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim(); if (remaining > 0) @@ -802,7 +803,7 @@ Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { extras = true; obj[key] = this[key]; return obj; - }, Object.create(null)); + }, create(null)); if (extras) { if (this.length !== 0) str += ', '; @@ -1042,7 +1043,7 @@ Buffer.prototype.toJSON = function toJSON() { function adjustOffset(offset, length) { // Use Math.trunc() to convert offset to an integer value that can be larger // than an Int32. Hence, don't use offset | 0 or similar techniques. - offset = Math.trunc(offset); + offset = trunc(offset); if (offset === 0) { return 0; } @@ -1163,7 +1164,7 @@ module.exports = { kStringMaxLength }; -Object.defineProperties(module.exports, { +defineProperties(module.exports, { constants: { configurable: false, enumerable: true, From 0a1d46423f5079b8aaa8816f3297285759ba8aa6 Mon Sep 17 00:00:00 2001 From: Jizu Sun Date: Sun, 3 Nov 2019 20:57:05 +0800 Subject: [PATCH 2/3] buffer: fix lint error --- lib/buffer.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 2ef6ef47fc9451..e27c993feb4307 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -21,8 +21,19 @@ 'use strict'; -const { Object: { defineProperties, defineProperty, setPrototypeOf, create } } = primordials; -const { Math: { floor, trunc, min } } = primordials; +const { + Object: { + defineProperties, + defineProperty, + setPrototypeOf, + create + }, + Math: { + floor, + trunc, + min + } +} = primordials; const { byteLengthUtf8, From d04e6d8b6a0e0929cbd203b7e4cb6c4bbbd33ea0 Mon Sep 17 00:00:00 2001 From: Jizu Sun Date: Mon, 4 Nov 2019 10:02:29 +0800 Subject: [PATCH 3/3] chore: more explicit names --- lib/buffer.js | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index e27c993feb4307..ab30db67010107 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -23,15 +23,15 @@ const { Object: { - defineProperties, - defineProperty, - setPrototypeOf, - create + defineProperties: ObjectDefineProperties, + defineProperty: ObjectDefineProperty, + setPrototypeOf: ObjectSetPrototypeOf, + create: ObjectCreate }, Math: { - floor, - trunc, - min + floor: MathFloor, + trunc: MathTrunc, + min: MathMin } } = primordials; @@ -101,7 +101,7 @@ FastBuffer.prototype.constructor = Buffer; Buffer.prototype = FastBuffer.prototype; addBufferPrototypeMethods(Buffer.prototype); -const constants = defineProperties({}, { +const constants = ObjectDefineProperties({}, { MAX_LENGTH: { value: kMaxLength, writable: false, @@ -123,7 +123,7 @@ let poolSize, poolOffset, allocPool; // do not own the ArrayBuffer allocator. Zero fill is always on in that case. const zeroFill = bindingZeroFill || [0]; -const encodingsMap = create(null); +const encodingsMap = ObjectCreate(null); for (let i = 0; i < encodings.length; ++i) encodingsMap[encodings[i]] = i; @@ -180,7 +180,7 @@ function toInteger(n, defaultVal) { if (!Number.isNaN(n) && n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER) { - return ((n % 1) === 0 ? n : floor(n)); + return ((n % 1) === 0 ? n : MathFloor(n)); } return defaultVal; } @@ -265,7 +265,7 @@ function Buffer(arg, encodingOrOffset, length) { return Buffer.from(arg, encodingOrOffset, length); } -defineProperty(Buffer, Symbol.species, { +ObjectDefineProperty(Buffer, Symbol.species, { enumerable: false, configurable: true, get() { return FastBuffer; } @@ -323,7 +323,7 @@ const of = (...items) => { }; Buffer.of = of; -setPrototypeOf(Buffer, Uint8Array); +ObjectSetPrototypeOf(Buffer, Uint8Array); // The 'assertSize' method will remove itself from the callstack when an error // occurs. This is done simply to keep the internal details of the @@ -376,8 +376,8 @@ function SlowBuffer(length) { return createUnsafeBuffer(length); } -setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); -setPrototypeOf(SlowBuffer, Uint8Array); +ObjectSetPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); +ObjectSetPrototypeOf(SlowBuffer, Uint8Array); function allocate(size) { if (size <= 0) { @@ -724,7 +724,7 @@ function byteLength(string, encoding) { Buffer.byteLength = byteLength; // For backwards compatibility. -defineProperty(Buffer.prototype, 'parent', { +ObjectDefineProperty(Buffer.prototype, 'parent', { enumerable: true, get() { if (!(this instanceof Buffer)) @@ -732,7 +732,7 @@ defineProperty(Buffer.prototype, 'parent', { return this.buffer; } }); -defineProperty(Buffer.prototype, 'offset', { +ObjectDefineProperty(Buffer.prototype, 'offset', { enumerable: true, get() { if (!(this instanceof Buffer)) @@ -801,7 +801,7 @@ let INSPECT_MAX_BYTES = 50; // Override how buffers are presented by util.inspect(). Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { const max = INSPECT_MAX_BYTES; - const actualMax = min(max, this.length); + const actualMax = MathMin(max, this.length); const remaining = this.length - max; let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim(); if (remaining > 0) @@ -814,7 +814,7 @@ Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { extras = true; obj[key] = this[key]; return obj; - }, create(null)); + }, ObjectCreate(null)); if (extras) { if (this.length !== 0) str += ', '; @@ -1054,7 +1054,7 @@ Buffer.prototype.toJSON = function toJSON() { function adjustOffset(offset, length) { // Use Math.trunc() to convert offset to an integer value that can be larger // than an Int32. Hence, don't use offset | 0 or similar techniques. - offset = trunc(offset); + offset = MathTrunc(offset); if (offset === 0) { return 0; } @@ -1175,7 +1175,7 @@ module.exports = { kStringMaxLength }; -defineProperties(module.exports, { +ObjectDefineProperties(module.exports, { constants: { configurable: false, enumerable: true,